forked from lug/matterbridge
Compare commits
227 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bd5a0d92d | ||
|
|
330ddb6a30 | ||
|
|
52dbd702ad | ||
|
|
d7c3570ba3 | ||
|
|
ab4d51b40b | ||
|
|
1665c93d3b | ||
|
|
b51fdbce9f | ||
|
|
351b423e15 | ||
|
|
7690be1647 | ||
|
|
68aeb93afa | ||
|
|
51062863a5 | ||
|
|
4fb4b7aa6c | ||
|
|
7f3cbcedc0 | ||
|
|
6ef09def81 | ||
|
|
c4c6aff9a5 | ||
|
|
d71850cef6 | ||
|
|
2597c9bfac | ||
|
|
93307b57aa | ||
|
|
618953c865 | ||
|
|
e04dd78624 | ||
|
|
fa0c4025f7 | ||
|
|
2d2d185200 | ||
|
|
cb7278eb50 | ||
|
|
89aa114192 | ||
|
|
ed062e0ce5 | ||
|
|
a69ef8402b | ||
|
|
8779f67d2d | ||
|
|
e4b72136b8 | ||
|
|
4ff5091bc2 | ||
|
|
6f131250f1 | ||
|
|
221a63d980 | ||
|
|
d02eda147c | ||
|
|
9b25716136 | ||
|
|
6628a47f23 | ||
|
|
ec0e6bc3f8 | ||
|
|
d2c02be3a0 | ||
|
|
594492fbdd | ||
|
|
bd9ea7a88d | ||
|
|
51327a4056 | ||
|
|
33bd60528b | ||
|
|
7e54474111 | ||
|
|
e307069d62 | ||
|
|
91db63294c | ||
|
|
fd04e08c9c | ||
|
|
6576409d60 | ||
|
|
045cb2058c | ||
|
|
d03afc12fd | ||
|
|
48799a3cff | ||
|
|
dba259e9f1 | ||
|
|
07885f5810 | ||
|
|
696c518550 | ||
|
|
411ef2691c | ||
|
|
fc6074ea9f | ||
|
|
ab1670e2ce | ||
|
|
9142a33bbf | ||
|
|
f6eefa4ecc | ||
|
|
f1db166ac4 | ||
|
|
887c2bc56d | ||
|
|
f0738a93c3 | ||
|
|
75381c2c6e | ||
|
|
bf0b9959d1 | ||
|
|
406a54b597 | ||
|
|
be04d1a862 | ||
|
|
85b2d5a124 | ||
|
|
521a7ed7b0 | ||
|
|
529b188164 | ||
|
|
8d307d8134 | ||
|
|
8c675b52bc | ||
|
|
aa51aa2aa0 | ||
|
|
86865c6da5 | ||
|
|
45296100df | ||
|
|
1605fbc012 | ||
|
|
c6c92e273d | ||
|
|
467b373c43 | ||
|
|
72ce7f06e9 | ||
|
|
346a7284f7 | ||
|
|
ee4ac67081 | ||
|
|
5a93d14d75 | ||
|
|
96a47a60ad | ||
|
|
b24a47ad7f | ||
|
|
cd1fd1bb7c | ||
|
|
d44df7b6e6 | ||
|
|
9d1ac0c84b | ||
|
|
76af9cba5a | ||
|
|
b69fc30902 | ||
|
|
c3174f4de9 | ||
|
|
99ce68e9ba | ||
|
|
0cf73673a9 | ||
|
|
08f442dc7b | ||
|
|
8a8b95228c | ||
|
|
31a752fa21 | ||
|
|
a83831e68d | ||
|
|
a12a8d4fe2 | ||
|
|
e57f3a7e6c | ||
|
|
68fbed9281 | ||
|
|
8bfaa007d5 | ||
|
|
76360f89c1 | ||
|
|
d525230abd | ||
|
|
b4aa637d41 | ||
|
|
7c4334d0de | ||
|
|
062be8d7c9 | ||
|
|
db25ee59c5 | ||
|
|
4b0bc6d0bf | ||
|
|
8c0b04b995 | ||
|
|
e5989adf92 | ||
|
|
9e5da2f9d7 | ||
|
|
a284a228a3 | ||
|
|
2133e0d1be | ||
|
|
a6f37f1d61 | ||
|
|
9de9151826 | ||
|
|
fdd5ada98c | ||
|
|
80fcf18e24 | ||
|
|
ab94b5ca7a | ||
|
|
8d2ce56c37 | ||
|
|
1ec324354b | ||
|
|
16be6601c8 | ||
|
|
98027446c8 | ||
|
|
f2f1d874e1 | ||
|
|
25a72113b1 | ||
|
|
79c4ad5015 | ||
|
|
e24f1c7c87 | ||
|
|
dbf8a326d5 | ||
|
|
0bc9c70c66 | ||
|
|
594d2155e3 | ||
|
|
20dbd71306 | ||
|
|
6a727b9723 | ||
|
|
02a5bc096f | ||
|
|
2110db6f0c | ||
|
|
2bac867382 | ||
|
|
5fbd8a3be0 | ||
|
|
ad6440b603 | ||
|
|
064b6a915f | ||
|
|
1578ebb0e2 | ||
|
|
73525a4bbc | ||
|
|
d62f49d1fc | ||
|
|
63b88e77f2 | ||
|
|
3d8f15c20b | ||
|
|
cac5d56d60 | ||
|
|
bd2a672c14 | ||
|
|
82396e73f5 | ||
|
|
ba928b169d | ||
|
|
4fed720f97 | ||
|
|
78238c85d4 | ||
|
|
4f2ae7b73f | ||
|
|
f82a9cc7ac | ||
|
|
cce7624ab8 | ||
|
|
c5ecd09172 | ||
|
|
7b21c1c2f4 | ||
|
|
f8714d81f5 | ||
|
|
8622656005 | ||
|
|
52237fadb6 | ||
|
|
222cccf388 | ||
|
|
bab308508e | ||
|
|
dedb83c867 | ||
|
|
723a90cdd6 | ||
|
|
67d2398fa8 | ||
|
|
5f3b6ec007 | ||
|
|
55ab0c12f1 | ||
|
|
d1227b5fc9 | ||
|
|
6ea368c383 | ||
|
|
e92b6de09f | ||
|
|
e622587db4 | ||
|
|
f2efc06d1f | ||
|
|
a2b94452db | ||
|
|
4c506f7cc3 | ||
|
|
7886f05e88 | ||
|
|
f58be0d1c1 | ||
|
|
1152394bc1 | ||
|
|
a082b5a590 | ||
|
|
bae9484df2 | ||
|
|
6f78485878 | ||
|
|
fd0fe3390b | ||
|
|
2522158127 | ||
|
|
8be107cecc | ||
|
|
5aab158c0b | ||
|
|
1d33e60e36 | ||
|
|
83c28cb857 | ||
|
|
df5bce27b0 | ||
|
|
2b15739b48 | ||
|
|
3480c88e90 | ||
|
|
432cd0f99d | ||
|
|
e8b3e9b22d | ||
|
|
d4a47671ea | ||
|
|
0bcd1e62f3 | ||
|
|
80822b7fff | ||
|
|
78f1011f52 | ||
|
|
67f6257617 | ||
|
|
169c614489 | ||
|
|
da908c438a | ||
|
|
9c9c4bf1f9 | ||
|
|
7764493298 | ||
|
|
64a20ee61b | ||
|
|
62d1af8c37 | ||
|
|
0f5274fdf6 | ||
|
|
2e2187ebf4 | ||
|
|
762c3350f4 | ||
|
|
e1a4d7f77e | ||
|
|
a7a4554a85 | ||
|
|
6bd808ce91 | ||
|
|
a5c143bc46 | ||
|
|
87c9cac756 | ||
|
|
6a047f8722 | ||
|
|
6523494e83 | ||
|
|
7c6ce8bb90 | ||
|
|
dafbfe4021 | ||
|
|
a4d5c94d9b | ||
|
|
7119e378a7 | ||
|
|
e1dc3032c1 | ||
|
|
5de03b8921 | ||
|
|
7631d43c48 | ||
|
|
d0b2ee5c85 | ||
|
|
8830a5a1df | ||
|
|
ee87626a93 | ||
|
|
9f15d38c1c | ||
|
|
4a96a977c0 | ||
|
|
9a95293bdf | ||
|
|
0b3a06d263 | ||
|
|
9a6249c4f5 | ||
|
|
50bd51e461 | ||
|
|
04f8013314 | ||
|
|
a0aaf0057a | ||
|
|
8e78b3e6be | ||
|
|
57a503818d | ||
|
|
25d2ff3e9b | ||
|
|
31902d3e57 | ||
|
|
16f3fa6bae | ||
|
|
1f706673cf |
28
.github/ISSUE_TEMPLATE.md
vendored
28
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,22 +1,36 @@
|
|||||||
If you have a configuration problem, please first try to create a basic configuration following the instructions on [the wiki](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) before filing an issue.
|
<!-- This is a bug report template. By following the instructions below and
|
||||||
|
filling out the sections with your information, you will help the us to get all
|
||||||
|
the necessary data to fix your issue.
|
||||||
|
|
||||||
Please answer the following questions.
|
You can also preview your report before submitting it.
|
||||||
|
|
||||||
### Which version of matterbridge are you using?
|
Text between <!-- and --> marks will be invisible in the report.
|
||||||
run ```matterbridge -version```
|
-->
|
||||||
|
|
||||||
### If you're having problems with mattermost please specify mattermost version.
|
<!-- If you have a configuration problem, please first try to create a basic configuration following the instructions on [the wiki](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) before filing an issue. -->
|
||||||
|
|
||||||
|
|
||||||
|
### Environment
|
||||||
|
<!-- run `matterbridge -version` -->
|
||||||
|
<!-- If you're having problems with mattermost also specify the mattermost version. -->
|
||||||
|
Version:
|
||||||
|
|
||||||
|
<!-- What operating system are you using ? (be as specific as possible) -->
|
||||||
|
Operating system:
|
||||||
|
|
||||||
|
<!-- If you compiled matterbridge yourself:
|
||||||
|
* Specify the output of `go version`
|
||||||
|
* Specify the output of `git rev-parse HEAD` -->
|
||||||
|
|
||||||
### Please describe the expected behavior.
|
### Please describe the expected behavior.
|
||||||
|
|
||||||
|
|
||||||
### Please describe the actual behavior.
|
### Please describe the actual behavior.
|
||||||
#### Use logs from running ```matterbridge -debug``` if possible.
|
<!-- Use logs from running `matterbridge -debug` if possible. -->
|
||||||
|
|
||||||
|
|
||||||
### Any steps to reproduce the behavior?
|
### Any steps to reproduce the behavior?
|
||||||
|
|
||||||
|
|
||||||
### Please add your configuration file
|
### Please add your configuration file
|
||||||
#### (be sure to exclude or anonymize private data (tokens/passwords))
|
<!-- (be sure to exclude or anonymize private data (tokens/passwords)) -->
|
||||||
|
|||||||
26
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve. (Check the FAQ on the wiki first)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots/debug logs**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
Use logs from running `matterbridge -debug` if possible.
|
||||||
|
|
||||||
|
**Environment (please complete the following information):**
|
||||||
|
- OS: [e.g. linux]
|
||||||
|
- Matterbridge version: output of `matterbridge -version`
|
||||||
|
- If self compiled: output of `git rev-parse HEAD`
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Please add your configuration file (be sure to exclude or anonymize private data (tokens/passwords))
|
||||||
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
#- 1.7.x
|
#- 1.7.x
|
||||||
- 1.9.x
|
- 1.10.x
|
||||||
# - tip
|
# - tip
|
||||||
|
|
||||||
# we have everything vendored
|
# we have everything vendored
|
||||||
@@ -34,15 +34,17 @@ before_script:
|
|||||||
# flunk the build and immediately stop. It's sorta like having
|
# flunk the build and immediately stop. It's sorta like having
|
||||||
# set -e enabled in bash.
|
# set -e enabled in bash.
|
||||||
script:
|
script:
|
||||||
- test -z $(gofmt -s -l $GO_FILES) # Fail if a .go file hasn't been formatted with gofmt
|
#- test -z $(gofmt -s -l $GO_FILES) # Fail if a .go file hasn't been formatted with gofmt
|
||||||
- go test -v -race $PKGS # Run all the tests with the race detector enabled
|
- go test -v -race $PKGS # Run all the tests with the race detector enabled
|
||||||
- go vet $PKGS # go vet is the official Go static analyzer
|
# - go vet $PKGS # go vet is the official Go static analyzer
|
||||||
- megacheck $PKGS # "go vet on steroids" + linter
|
- megacheck $PKGS # "go vet on steroids" + linter
|
||||||
- /bin/bash ci/bintray.sh
|
- /bin/bash ci/bintray.sh
|
||||||
#- golint -set_exit_status $PKGS # one last linter
|
#- golint -set_exit_status $PKGS # one last linter
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
provider: bintray
|
provider: bintray
|
||||||
|
edge:
|
||||||
|
branch: v1.8.47
|
||||||
file: ci/deploy.json
|
file: ci/deploy.json
|
||||||
user: 42wim
|
user: 42wim
|
||||||
key:
|
key:
|
||||||
|
|||||||
51
README.md
51
README.md
@@ -1,17 +1,21 @@
|
|||||||
# matterbridge
|
# matterbridge
|
||||||
Click on one of the badges below to join the chat
|
Click on one of the badges below to join the chat
|
||||||
|
|
||||||
[](https://gitter.im/42wim/matterbridge) [](https://webchat.freenode.net/?channels=matterbridgechat) [](https://discord.gg/AkKPtrQ) [](https://riot.im/app/#/room/#matterbridge:matrix.org) [](https://join.slack.com/matterbridgechat/shared_invite/MjEwODMxNjU1NDMwLTE0OTk2MTU3NTMtMzZkZmRiNDZhOA) [](https://framateam.org/signup_user_complete/?id=tfqm33ggop8x3qgu4boeieta6e) 
|
[](https://gitter.im/42wim/matterbridge) [](https://webchat.freenode.net/?channels=matterbridgechat) [](https://discord.gg/AkKPtrQ) [](https://riot.im/app/#/room/#matterbridge:matrix.org) [](https://join.slack.com/matterbridgechat/shared_invite/MjEwODMxNjU1NDMwLTE0OTk2MTU3NTMtMzZkZmRiNDZhOA) [](https://framateam.org/signup_user_complete/?id=tfqm33ggop8x3qgu4boeieta6e) [](https://inverse.chat) [](https://www.twitch.tv/matterbridge) [](https://matterbridge.zulipchat.com/register/)
|
||||||
|
|
||||||
[](https://github.com/42wim/matterbridge/releases/latest) [](https://bintray.com/42wim/nightly/Matterbridge/_latestVersion)
|
[](https://github.com/42wim/matterbridge/releases/latest) [](https://bintray.com/42wim/nightly/Matterbridge/_latestVersion)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Simple bridge between Mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, Rocket.Chat, Hipchat(via xmpp), Matrix and Steam.
|
Simple bridge between IRC, XMPP, Gitter, Mattermost, Slack, Discord, Telegram, Rocket.Chat, Hipchat(via xmpp), Matrix, Steam, ssh-chat and Zulip
|
||||||
Has a REST API.
|
Has a REST API.
|
||||||
|
Minecraft server chat support via [MatterLink](https://github.com/elytra/MatterLink)
|
||||||
|
|
||||||
|
**Mattermost isn't required to run matterbridge. It bridges between any supported protocol.**
|
||||||
|
(The name matterbridge is a remnant when it was only bridging mattermost)
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
* [Features](#features)
|
* [Features](https://github.com/42wim/matterbridge/wiki/Features)
|
||||||
* [Requirements](#requirements)
|
* [Requirements](#requirements)
|
||||||
* [Screenshots](https://github.com/42wim/matterbridge/wiki/)
|
* [Screenshots](https://github.com/42wim/matterbridge/wiki/)
|
||||||
* [Installing](#installing)
|
* [Installing](#installing)
|
||||||
@@ -27,17 +31,25 @@ Has a REST API.
|
|||||||
* [Thanks](#thanks)
|
* [Thanks](#thanks)
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
* Relays public channel messages between multiple mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, Rocket.Chat, Hipchat (via xmpp), Matrix and Steam.
|
* [Support bridging between any protocols](https://github.com/42wim/matterbridge/wiki/Features#support-bridging-between-any-protocols)
|
||||||
Pick and mix.
|
* [Support multiple gateways(bridges) for your protocols](https://github.com/42wim/matterbridge/wiki/Features#support-multiple-gatewaysbridges-for-your-protocols)
|
||||||
* Support private groups on your mattermost/slack.
|
* [Message edits and deletes](https://github.com/42wim/matterbridge/wiki/Features#message-edits-and-deletes)
|
||||||
* Allow for bridging the same bridges, which means you can eg bridge between multiple mattermosts.
|
* [Attachment / files handling](https://github.com/42wim/matterbridge/wiki/Features#attachment--files-handling)
|
||||||
* The bridge is now a gateway which has support multiple in and out bridges. (and supports multiple gateways).
|
* [Username and avatar spoofing](https://github.com/42wim/matterbridge/wiki/Features#username-and-avatar-spoofing)
|
||||||
* Edits and delete messages across bridges that support it (mattermost,slack,discord,gitter,telegram)
|
* [Private groups](https://github.com/42wim/matterbridge/wiki/Features#private-groups)
|
||||||
* REST API to read/post messages to bridges (WIP).
|
* [API](https://github.com/42wim/matterbridge/wiki/Features#api)
|
||||||
|
|
||||||
|
## API
|
||||||
|
The API is very basic at the moment and rather undocumented.
|
||||||
|
|
||||||
|
Used by at least 2 projects. 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)
|
||||||
|
* [pyCord](https://github.com/NikkyAI/pyCord) (crossplatform chatbot)
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
Accounts to one of the supported bridges
|
Accounts to one of the supported bridges
|
||||||
* [Mattermost](https://github.com/mattermost/platform/) 3.8.x - 3.10.x, 4.x
|
* [Mattermost](https://github.com/mattermost/platform/) 3.8.x - 3.10.x, 4.x, 5.x
|
||||||
* [IRC](http://www.mirc.com/servers.html)
|
* [IRC](http://www.mirc.com/servers.html)
|
||||||
* [XMPP](https://jabber.org)
|
* [XMPP](https://jabber.org)
|
||||||
* [Gitter](https://gitter.im)
|
* [Gitter](https://gitter.im)
|
||||||
@@ -48,17 +60,22 @@ Accounts to one of the supported bridges
|
|||||||
* [Rocket.chat](https://rocket.chat)
|
* [Rocket.chat](https://rocket.chat)
|
||||||
* [Matrix](https://matrix.org)
|
* [Matrix](https://matrix.org)
|
||||||
* [Steam](https://store.steampowered.com/)
|
* [Steam](https://store.steampowered.com/)
|
||||||
|
* [Twitch](https://twitch.tv)
|
||||||
|
* [Ssh-chat](https://github.com/shazow/ssh-chat)
|
||||||
|
* [Zulip](https://zulipchat.com)
|
||||||
|
|
||||||
# Screenshots
|
# Screenshots
|
||||||
See https://github.com/42wim/matterbridge/wiki
|
See https://github.com/42wim/matterbridge/wiki
|
||||||
|
|
||||||
# Installing
|
# Installing
|
||||||
## Binaries
|
## Binaries
|
||||||
* Latest stable release [v1.6.0](https://github.com/42wim/matterbridge/releases/latest)
|
* Latest stable release [v1.11.3](https://github.com/42wim/matterbridge/releases/latest)
|
||||||
* Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)
|
* Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
Go 1.8+ is required. Make sure you have [Go](https://golang.org/doc/install) properly installed, including setting up your [GOPATH] (https://golang.org/doc/code.html#GOPATH)
|
Go 1.8+ is required. Make sure you have [Go](https://golang.org/doc/install) properly installed, including setting up your [GOPATH](https://golang.org/doc/code.html#GOPATH).
|
||||||
|
|
||||||
|
After Go is setup, download matterbridge to your $GOPATH directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
cd $GOPATH
|
cd $GOPATH
|
||||||
@@ -170,11 +187,14 @@ Want to tip ?
|
|||||||
* btc: 1N7cKHj5SfqBHBzDJ6kad4BzeqUBBS2zhs
|
* btc: 1N7cKHj5SfqBHBzDJ6kad4BzeqUBBS2zhs
|
||||||
|
|
||||||
# Thanks
|
# Thanks
|
||||||
|
[](https://www.digitalocean.com/) for sponsoring demo/testing droplets.
|
||||||
|
|
||||||
Matterbridge wouldn't exist without these libraries:
|
Matterbridge wouldn't exist without these libraries:
|
||||||
* discord - https://github.com/bwmarrin/discordgo
|
* discord - https://github.com/bwmarrin/discordgo
|
||||||
* echo - https://github.com/labstack/echo
|
* echo - https://github.com/labstack/echo
|
||||||
* gitter - https://github.com/sromku/go-gitter
|
* gitter - https://github.com/sromku/go-gitter
|
||||||
* gops - https://github.com/google/gops
|
* gops - https://github.com/google/gops
|
||||||
|
* gozulipbot - https://github.com/ifo/gozulipbot
|
||||||
* irc - https://github.com/lrstanley/girc
|
* irc - https://github.com/lrstanley/girc
|
||||||
* mattermost - https://github.com/mattermost/platform
|
* mattermost - https://github.com/mattermost/platform
|
||||||
* matrix - https://github.com/matrix-org/gomatrix
|
* matrix - https://github.com/matrix-org/gomatrix
|
||||||
@@ -182,3 +202,4 @@ Matterbridge wouldn't exist without these libraries:
|
|||||||
* steam - https://github.com/Philipp15b/go-steam
|
* steam - https://github.com/Philipp15b/go-steam
|
||||||
* telegram - https://github.com/go-telegram-bot-api/telegram-bot-api
|
* telegram - https://github.com/go-telegram-bot-api/telegram-bot-api
|
||||||
* xmpp - https://github.com/mattn/go-xmpp
|
* xmpp - https://github.com/mattn/go-xmpp
|
||||||
|
* zulip - https://github.com/ifo/gozulipbot
|
||||||
|
|||||||
@@ -2,20 +2,21 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/labstack/echo"
|
|
||||||
"github.com/labstack/echo/middleware"
|
|
||||||
"github.com/zfjagann/golang-ring"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
"github.com/labstack/echo/middleware"
|
||||||
|
"github.com/zfjagann/golang-ring"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Api struct {
|
type Api struct {
|
||||||
Messages ring.Ring
|
Messages ring.Ring
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiMessage struct {
|
type ApiMessage struct {
|
||||||
@@ -26,28 +27,27 @@ type ApiMessage struct {
|
|||||||
Gateway string `json:"gateway"`
|
Gateway string `json:"gateway"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "api"
|
b := &Api{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Api {
|
|
||||||
b := &Api{BridgeConfig: cfg}
|
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
|
e.HideBanner = true
|
||||||
|
e.HidePort = true
|
||||||
b.Messages = ring.Ring{}
|
b.Messages = ring.Ring{}
|
||||||
b.Messages.SetCapacity(b.Config.Buffer)
|
b.Messages.SetCapacity(b.GetInt("Buffer"))
|
||||||
if b.Config.Token != "" {
|
if b.GetString("Token") != "" {
|
||||||
e.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
|
e.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
|
||||||
return key == b.Config.Token, nil
|
return key == b.GetString("Token"), nil
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
e.GET("/api/messages", b.handleMessages)
|
e.GET("/api/messages", b.handleMessages)
|
||||||
e.GET("/api/stream", b.handleStream)
|
e.GET("/api/stream", b.handleStream)
|
||||||
e.POST("/api/message", b.handlePostMessage)
|
e.POST("/api/message", b.handlePostMessage)
|
||||||
go func() {
|
go func() {
|
||||||
flog.Fatal(e.Start(b.Config.BindAddress))
|
if b.GetString("BindAddress") == "" {
|
||||||
|
b.Log.Fatalf("No BindAddress configured.")
|
||||||
|
}
|
||||||
|
b.Log.Infof("Listening on %s", b.GetString("BindAddress"))
|
||||||
|
b.Log.Fatal(e.Start(b.GetString("BindAddress")))
|
||||||
}()
|
}()
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@@ -76,21 +76,18 @@ func (b *Api) Send(msg config.Message) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Api) handlePostMessage(c echo.Context) error {
|
func (b *Api) handlePostMessage(c echo.Context) error {
|
||||||
message := &ApiMessage{}
|
message := config.Message{}
|
||||||
if err := c.Bind(message); err != nil {
|
if err := c.Bind(&message); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", message.Username, "api")
|
// these values are fixed
|
||||||
b.Remote <- config.Message{
|
message.Channel = "api"
|
||||||
Text: message.Text,
|
message.Protocol = "api"
|
||||||
Username: message.Username,
|
message.Account = b.Account
|
||||||
UserID: message.UserID,
|
message.ID = ""
|
||||||
Channel: "api",
|
message.Timestamp = time.Now()
|
||||||
Avatar: message.Avatar,
|
b.Log.Debugf("Sending message from %s on %s to gateway", message.Username, "api")
|
||||||
Account: b.Account,
|
b.Remote <- message
|
||||||
Gateway: message.Gateway,
|
|
||||||
Protocol: "api",
|
|
||||||
}
|
|
||||||
return c.JSON(http.StatusOK, message)
|
return c.JSON(http.StatusOK, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
109
bridge/bridge.go
109
bridge/bridge.go
@@ -1,20 +1,8 @@
|
|||||||
package bridge
|
package bridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/42wim/matterbridge/bridge/api"
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/discord"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/42wim/matterbridge/bridge/gitter"
|
|
||||||
"github.com/42wim/matterbridge/bridge/irc"
|
|
||||||
"github.com/42wim/matterbridge/bridge/matrix"
|
|
||||||
"github.com/42wim/matterbridge/bridge/mattermost"
|
|
||||||
"github.com/42wim/matterbridge/bridge/rocketchat"
|
|
||||||
"github.com/42wim/matterbridge/bridge/slack"
|
|
||||||
"github.com/42wim/matterbridge/bridge/sshchat"
|
|
||||||
"github.com/42wim/matterbridge/bridge/steam"
|
|
||||||
"github.com/42wim/matterbridge/bridge/telegram"
|
|
||||||
"github.com/42wim/matterbridge/bridge/xmpp"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -27,16 +15,28 @@ type Bridger interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Bridge struct {
|
type Bridge struct {
|
||||||
Config config.Protocol
|
|
||||||
Bridger
|
Bridger
|
||||||
Name string
|
Name string
|
||||||
Account string
|
Account string
|
||||||
Protocol string
|
Protocol string
|
||||||
Channels map[string]config.ChannelInfo
|
Channels map[string]config.ChannelInfo
|
||||||
Joined map[string]bool
|
Joined map[string]bool
|
||||||
|
Log *log.Entry
|
||||||
|
Config *config.Config
|
||||||
|
General *config.Protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Bridge {
|
type Config struct {
|
||||||
|
// General *config.Protocol
|
||||||
|
Remote chan config.Message
|
||||||
|
Log *log.Entry
|
||||||
|
*Bridge
|
||||||
|
}
|
||||||
|
|
||||||
|
// Factory is the factory function to create a bridge
|
||||||
|
type Factory func(*Config) Bridger
|
||||||
|
|
||||||
|
func New(bridge *config.Bridge) *Bridge {
|
||||||
b := new(Bridge)
|
b := new(Bridge)
|
||||||
b.Channels = make(map[string]config.ChannelInfo)
|
b.Channels = make(map[string]config.ChannelInfo)
|
||||||
accInfo := strings.Split(bridge.Account, ".")
|
accInfo := strings.Split(bridge.Account, ".")
|
||||||
@@ -46,48 +46,6 @@ func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Brid
|
|||||||
b.Protocol = protocol
|
b.Protocol = protocol
|
||||||
b.Account = bridge.Account
|
b.Account = bridge.Account
|
||||||
b.Joined = make(map[string]bool)
|
b.Joined = make(map[string]bool)
|
||||||
bridgeConfig := &config.BridgeConfig{General: &cfg.General, Account: bridge.Account, Remote: c}
|
|
||||||
|
|
||||||
// override config from environment
|
|
||||||
config.OverrideCfgFromEnv(cfg, protocol, name)
|
|
||||||
switch protocol {
|
|
||||||
case "mattermost":
|
|
||||||
bridgeConfig.Config = cfg.Mattermost[name]
|
|
||||||
b.Bridger = bmattermost.New(bridgeConfig)
|
|
||||||
case "irc":
|
|
||||||
bridgeConfig.Config = cfg.IRC[name]
|
|
||||||
b.Bridger = birc.New(bridgeConfig)
|
|
||||||
case "gitter":
|
|
||||||
bridgeConfig.Config = cfg.Gitter[name]
|
|
||||||
b.Bridger = bgitter.New(bridgeConfig)
|
|
||||||
case "slack":
|
|
||||||
bridgeConfig.Config = cfg.Slack[name]
|
|
||||||
b.Bridger = bslack.New(bridgeConfig)
|
|
||||||
case "xmpp":
|
|
||||||
bridgeConfig.Config = cfg.Xmpp[name]
|
|
||||||
b.Bridger = bxmpp.New(bridgeConfig)
|
|
||||||
case "discord":
|
|
||||||
bridgeConfig.Config = cfg.Discord[name]
|
|
||||||
b.Bridger = bdiscord.New(bridgeConfig)
|
|
||||||
case "telegram":
|
|
||||||
bridgeConfig.Config = cfg.Telegram[name]
|
|
||||||
b.Bridger = btelegram.New(bridgeConfig)
|
|
||||||
case "rocketchat":
|
|
||||||
bridgeConfig.Config = cfg.Rocketchat[name]
|
|
||||||
b.Bridger = brocketchat.New(bridgeConfig)
|
|
||||||
case "matrix":
|
|
||||||
bridgeConfig.Config = cfg.Matrix[name]
|
|
||||||
b.Bridger = bmatrix.New(bridgeConfig)
|
|
||||||
case "steam":
|
|
||||||
bridgeConfig.Config = cfg.Steam[name]
|
|
||||||
b.Bridger = bsteam.New(bridgeConfig)
|
|
||||||
case "sshchat":
|
|
||||||
bridgeConfig.Config = cfg.Sshchat[name]
|
|
||||||
b.Bridger = bsshchat.New(bridgeConfig)
|
|
||||||
case "api":
|
|
||||||
bridgeConfig.Config = cfg.Api[name]
|
|
||||||
b.Bridger = api.New(bridgeConfig)
|
|
||||||
}
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +57,7 @@ func (b *Bridge) JoinChannels() error {
|
|||||||
func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map[string]bool) error {
|
func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map[string]bool) error {
|
||||||
for ID, channel := range channels {
|
for ID, channel := range channels {
|
||||||
if !exists[ID] {
|
if !exists[ID] {
|
||||||
log.Infof("%s: joining %s (%s)", b.Account, channel.Name, ID)
|
b.Log.Infof("%s: joining %s (ID: %s)", b.Account, channel.Name, ID)
|
||||||
err := b.JoinChannel(channel)
|
err := b.JoinChannel(channel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -109,3 +67,38 @@ func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) GetBool(key string) bool {
|
||||||
|
if b.Config.GetBool(b.Account + "." + key) {
|
||||||
|
return b.Config.GetBool(b.Account + "." + key)
|
||||||
|
}
|
||||||
|
return b.Config.GetBool("general." + key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) GetInt(key string) int {
|
||||||
|
if b.Config.GetInt(b.Account+"."+key) != 0 {
|
||||||
|
return b.Config.GetInt(b.Account + "." + key)
|
||||||
|
}
|
||||||
|
return b.Config.GetInt("general." + key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) GetString(key string) string {
|
||||||
|
if b.Config.GetString(b.Account+"."+key) != "" {
|
||||||
|
return b.Config.GetString(b.Account + "." + key)
|
||||||
|
}
|
||||||
|
return b.Config.GetString("general." + key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) GetStringSlice(key string) []string {
|
||||||
|
if len(b.Config.GetStringSlice(b.Account+"."+key)) != 0 {
|
||||||
|
return b.Config.GetStringSlice(b.Account + "." + key)
|
||||||
|
}
|
||||||
|
return b.Config.GetStringSlice("general." + key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) GetStringSlice2D(key string) [][]string {
|
||||||
|
if len(b.Config.GetStringSlice2D(b.Account+"."+key)) != 0 {
|
||||||
|
return b.Config.GetStringSlice2D(b.Account + "." + key)
|
||||||
|
}
|
||||||
|
return b.Config.GetStringSlice2D("general." + key)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,27 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/BurntSushi/toml"
|
"bytes"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
|
prefixed "github.com/matterbridge/logrus-prefixed-formatter"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EVENT_JOIN_LEAVE = "join_leave"
|
EVENT_JOIN_LEAVE = "join_leave"
|
||||||
EVENT_FAILURE = "failure"
|
EVENT_TOPIC_CHANGE = "topic_change"
|
||||||
EVENT_REJOIN_CHANNELS = "rejoin_channels"
|
EVENT_FAILURE = "failure"
|
||||||
EVENT_USER_ACTION = "user_action"
|
EVENT_FILE_FAILURE_SIZE = "file_failure_size"
|
||||||
EVENT_MSG_DELETE = "msg_delete"
|
EVENT_AVATAR_DOWNLOAD = "avatar_download"
|
||||||
|
EVENT_REJOIN_CHANNELS = "rejoin_channels"
|
||||||
|
EVENT_USER_ACTION = "user_action"
|
||||||
|
EVENT_MSG_DELETE = "msg_delete"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
@@ -37,6 +44,9 @@ type FileInfo struct {
|
|||||||
Data *[]byte
|
Data *[]byte
|
||||||
Comment string
|
Comment string
|
||||||
URL string
|
URL string
|
||||||
|
Size int64
|
||||||
|
Avatar bool
|
||||||
|
SHA string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelInfo struct {
|
type ChannelInfo struct {
|
||||||
@@ -53,13 +63,19 @@ type Protocol struct {
|
|||||||
BindAddress string // mattermost, slack // DEPRECATED
|
BindAddress string // mattermost, slack // DEPRECATED
|
||||||
Buffer int // api
|
Buffer int // api
|
||||||
Charset string // irc
|
Charset string // irc
|
||||||
|
ColorNicks bool // only irc for now
|
||||||
|
Debug bool // general
|
||||||
|
DebugLevel int // only for irc now
|
||||||
EditSuffix string // mattermost, slack, discord, telegram, gitter
|
EditSuffix string // mattermost, slack, discord, telegram, gitter
|
||||||
EditDisable bool // mattermost, slack, discord, telegram, gitter
|
EditDisable bool // mattermost, slack, discord, telegram, gitter
|
||||||
IconURL string // mattermost, slack
|
IconURL string // mattermost, slack
|
||||||
IgnoreNicks string // all protocols
|
IgnoreNicks string // all protocols
|
||||||
IgnoreMessages string // all protocols
|
IgnoreMessages string // all protocols
|
||||||
Jid string // xmpp
|
Jid string // xmpp
|
||||||
|
Label string // all protocols
|
||||||
Login string // mattermost, matrix
|
Login string // mattermost, matrix
|
||||||
|
MediaDownloadBlackList []string
|
||||||
|
MediaDownloadPath string // Basically MediaServerUpload, but instead of uploading it, just write it to a file on the same server.
|
||||||
MediaDownloadSize int // all protocols
|
MediaDownloadSize int // all protocols
|
||||||
MediaServerDownload string
|
MediaServerDownload string
|
||||||
MediaServerUpload string
|
MediaServerUpload string
|
||||||
@@ -77,21 +93,26 @@ type Protocol struct {
|
|||||||
NickServPassword string // IRC
|
NickServPassword string // IRC
|
||||||
NicksPerRow int // mattermost, slack
|
NicksPerRow int // mattermost, slack
|
||||||
NoHomeServerSuffix bool // matrix
|
NoHomeServerSuffix bool // matrix
|
||||||
|
NoSendJoinPart bool // all protocols
|
||||||
NoTLS bool // mattermost
|
NoTLS bool // mattermost
|
||||||
Password string // IRC,mattermost,XMPP,matrix
|
Password string // IRC,mattermost,XMPP,matrix
|
||||||
PrefixMessagesWithNick bool // mattemost, slack
|
PrefixMessagesWithNick bool // mattemost, slack
|
||||||
Protocol string // all protocols
|
Protocol string // all protocols
|
||||||
|
QuoteDisable bool // telegram
|
||||||
|
QuoteFormat string // telegram
|
||||||
RejoinDelay int // IRC
|
RejoinDelay int // IRC
|
||||||
ReplaceMessages [][]string // all protocols
|
ReplaceMessages [][]string // all protocols
|
||||||
ReplaceNicks [][]string // all protocols
|
ReplaceNicks [][]string // all protocols
|
||||||
RemoteNickFormat string // all protocols
|
RemoteNickFormat string // all protocols
|
||||||
Server string // IRC,mattermost,XMPP,discord
|
Server string // IRC,mattermost,XMPP,discord
|
||||||
ShowJoinPart bool // all protocols
|
ShowJoinPart bool // all protocols
|
||||||
|
ShowTopicChange bool // slack
|
||||||
ShowEmbeds bool // discord
|
ShowEmbeds bool // discord
|
||||||
SkipTLSVerify bool // IRC, mattermost
|
SkipTLSVerify bool // IRC, mattermost
|
||||||
StripNick bool // all protocols
|
StripNick bool // all protocols
|
||||||
Team string // mattermost
|
Team string // mattermost
|
||||||
Token string // gitter, slack, discord, api
|
Token string // gitter, slack, discord, api
|
||||||
|
Topic string // zulip
|
||||||
URL string // mattermost, slack // DEPRECATED
|
URL string // mattermost, slack // DEPRECATED
|
||||||
UseAPI bool // mattermost, slack
|
UseAPI bool // mattermost, slack
|
||||||
UseSASL bool // IRC
|
UseSASL bool // IRC
|
||||||
@@ -105,7 +126,7 @@ type Protocol struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ChannelOptions struct {
|
type ChannelOptions struct {
|
||||||
Key string // irc
|
Key string // irc, xmpp
|
||||||
WebhookURL string // discord
|
WebhookURL string // discord
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,9 +152,9 @@ type SameChannelGateway struct {
|
|||||||
Accounts []string
|
Accounts []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type ConfigValues struct {
|
||||||
Api map[string]Protocol
|
Api map[string]Protocol
|
||||||
IRC map[string]Protocol
|
Irc map[string]Protocol
|
||||||
Mattermost map[string]Protocol
|
Mattermost map[string]Protocol
|
||||||
Matrix map[string]Protocol
|
Matrix map[string]Protocol
|
||||||
Slack map[string]Protocol
|
Slack map[string]Protocol
|
||||||
@@ -144,90 +165,117 @@ type Config struct {
|
|||||||
Telegram map[string]Protocol
|
Telegram map[string]Protocol
|
||||||
Rocketchat map[string]Protocol
|
Rocketchat map[string]Protocol
|
||||||
Sshchat map[string]Protocol
|
Sshchat map[string]Protocol
|
||||||
|
Zulip map[string]Protocol
|
||||||
General Protocol
|
General Protocol
|
||||||
Gateway []Gateway
|
Gateway []Gateway
|
||||||
SameChannelGateway []SameChannelGateway
|
SameChannelGateway []SameChannelGateway
|
||||||
}
|
}
|
||||||
|
|
||||||
type BridgeConfig struct {
|
type Config struct {
|
||||||
Config Protocol
|
v *viper.Viper
|
||||||
General *Protocol
|
*ConfigValues
|
||||||
Account string
|
sync.RWMutex
|
||||||
Remote chan Message
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig(cfgfile string) *Config {
|
func NewConfig(cfgfile string) *Config {
|
||||||
var cfg Config
|
log.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: false})
|
||||||
if _, err := toml.DecodeFile(cfgfile, &cfg); err != nil {
|
flog := log.WithFields(log.Fields{"prefix": "config"})
|
||||||
|
var cfg ConfigValues
|
||||||
|
viper.SetConfigType("toml")
|
||||||
|
viper.SetConfigFile(cfgfile)
|
||||||
|
viper.SetEnvPrefix("matterbridge")
|
||||||
|
viper.AddConfigPath(".")
|
||||||
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
f, err := os.Open(cfgfile)
|
||||||
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
fail := false
|
err = viper.ReadConfig(f)
|
||||||
for k, v := range cfg.Mattermost {
|
if err != nil {
|
||||||
res := Deprecated(v, "mattermost."+k)
|
log.Fatal(err)
|
||||||
if res {
|
|
||||||
fail = res
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for k, v := range cfg.Slack {
|
err = viper.Unmarshal(&cfg)
|
||||||
res := Deprecated(v, "slack."+k)
|
if err != nil {
|
||||||
if res {
|
log.Fatal("blah", err)
|
||||||
fail = res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k, v := range cfg.Rocketchat {
|
|
||||||
res := Deprecated(v, "rocketchat."+k)
|
|
||||||
if res {
|
|
||||||
fail = res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if fail {
|
|
||||||
log.Fatalf("Fix your config. Please see changelog for more information")
|
|
||||||
}
|
}
|
||||||
|
mycfg := new(Config)
|
||||||
|
mycfg.v = viper.GetViper()
|
||||||
if cfg.General.MediaDownloadSize == 0 {
|
if cfg.General.MediaDownloadSize == 0 {
|
||||||
cfg.General.MediaDownloadSize = 1000000
|
cfg.General.MediaDownloadSize = 1000000
|
||||||
}
|
}
|
||||||
return &cfg
|
viper.WatchConfig()
|
||||||
|
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||||
|
flog.Println("Config file changed:", e.Name)
|
||||||
|
})
|
||||||
|
|
||||||
|
mycfg.ConfigValues = &cfg
|
||||||
|
return mycfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func OverrideCfgFromEnv(cfg *Config, protocol string, account string) {
|
func NewConfigFromString(input []byte) *Config {
|
||||||
var protoCfg Protocol
|
var cfg ConfigValues
|
||||||
val := reflect.ValueOf(cfg).Elem()
|
viper.SetConfigType("toml")
|
||||||
// loop over the Config struct
|
err := viper.ReadConfig(bytes.NewBuffer(input))
|
||||||
for i := 0; i < val.NumField(); i++ {
|
if err != nil {
|
||||||
typeField := val.Type().Field(i)
|
log.Fatal(err)
|
||||||
// look for the protocol map (both lowercase)
|
|
||||||
if strings.ToLower(typeField.Name) == protocol {
|
|
||||||
// get the Protocol struct from the map
|
|
||||||
data := val.Field(i).MapIndex(reflect.ValueOf(account))
|
|
||||||
protoCfg = data.Interface().(Protocol)
|
|
||||||
protoStruct := reflect.ValueOf(&protoCfg).Elem()
|
|
||||||
// loop over the found protocol struct
|
|
||||||
for i := 0; i < protoStruct.NumField(); i++ {
|
|
||||||
typeField := protoStruct.Type().Field(i)
|
|
||||||
// build our environment key (eg MATTERBRIDGE_MATTERMOST_WORK_LOGIN)
|
|
||||||
key := "matterbridge_" + protocol + "_" + account + "_" + typeField.Name
|
|
||||||
key = strings.ToUpper(key)
|
|
||||||
// search the environment
|
|
||||||
res := os.Getenv(key)
|
|
||||||
// if it exists and the current field is a string
|
|
||||||
// then update the current field
|
|
||||||
if res != "" {
|
|
||||||
fieldVal := protoStruct.Field(i)
|
|
||||||
if fieldVal.Kind() == reflect.String {
|
|
||||||
log.Printf("config: overriding %s from env with %s\n", key, res)
|
|
||||||
fieldVal.Set(reflect.ValueOf(res))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// update the map with the modified Protocol (cfg.Protocol[account] = Protocol)
|
|
||||||
val.Field(i).SetMapIndex(reflect.ValueOf(account), reflect.ValueOf(protoCfg))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
err = viper.Unmarshal(&cfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
mycfg := new(Config)
|
||||||
|
mycfg.v = viper.GetViper()
|
||||||
|
mycfg.ConfigValues = &cfg
|
||||||
|
return mycfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIconURL(msg *Message, cfg *Protocol) string {
|
func (c *Config) GetBool(key string) bool {
|
||||||
iconURL := cfg.IconURL
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
// log.Debugf("getting bool %s = %#v", key, c.v.GetBool(key))
|
||||||
|
return c.v.GetBool(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetInt(key string) int {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
// log.Debugf("getting int %s = %d", key, c.v.GetInt(key))
|
||||||
|
return c.v.GetInt(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetString(key string) string {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
// log.Debugf("getting String %s = %s", key, c.v.GetString(key))
|
||||||
|
return c.v.GetString(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetStringSlice(key string) []string {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
// log.Debugf("getting StringSlice %s = %#v", key, c.v.GetStringSlice(key))
|
||||||
|
return c.v.GetStringSlice(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetStringSlice2D(key string) [][]string {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
result := [][]string{}
|
||||||
|
if res, ok := c.v.Get(key).([]interface{}); ok {
|
||||||
|
for _, entry := range res {
|
||||||
|
result2 := []string{}
|
||||||
|
for _, entry2 := range entry.([]interface{}) {
|
||||||
|
result2 = append(result2, entry2.(string))
|
||||||
|
}
|
||||||
|
result = append(result, result2)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIconURL(msg *Message, iconURL string) string {
|
||||||
info := strings.Split(msg.Account, ".")
|
info := strings.Split(msg.Account, ".")
|
||||||
protocol := info[0]
|
protocol := info[0]
|
||||||
name := info[1]
|
name := info[1]
|
||||||
@@ -236,17 +284,3 @@ func GetIconURL(msg *Message, cfg *Protocol) string {
|
|||||||
iconURL = strings.Replace(iconURL, "{PROTOCOL}", protocol, -1)
|
iconURL = strings.Replace(iconURL, "{PROTOCOL}", protocol, -1)
|
||||||
return iconURL
|
return iconURL
|
||||||
}
|
}
|
||||||
|
|
||||||
func Deprecated(cfg Protocol, account string) bool {
|
|
||||||
if cfg.BindAddress != "" {
|
|
||||||
log.Printf("ERROR: %s BindAddress is deprecated, you need to change it to WebhookBindAddress.", account)
|
|
||||||
} else if cfg.URL != "" {
|
|
||||||
log.Printf("ERROR: %s URL is deprecated, you need to change it to WebhookURL.", account)
|
|
||||||
} else if cfg.UseAPI {
|
|
||||||
log.Printf("ERROR: %s UseAPI is deprecated, it's enabled by default, please remove it from your config file.", account)
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
//log.Fatalf("ERROR: Fix your config: %s", account)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,15 +2,20 @@ package bdiscord
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"fmt"
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/bwmarrin/discordgo"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
"github.com/matterbridge/discordgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bdiscord struct {
|
const MessageLength = 1950
|
||||||
|
|
||||||
|
type Bdiscord struct {
|
||||||
c *discordgo.Session
|
c *discordgo.Session
|
||||||
Channels []*discordgo.Channel
|
Channels []*discordgo.Channel
|
||||||
Nick string
|
Nick string
|
||||||
@@ -21,82 +26,74 @@ type bdiscord struct {
|
|||||||
webhookToken string
|
webhookToken string
|
||||||
channelInfoMap map[string]*config.ChannelInfo
|
channelInfoMap map[string]*config.ChannelInfo
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "discord"
|
b := &Bdiscord{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *bdiscord {
|
|
||||||
b := &bdiscord{BridgeConfig: cfg}
|
|
||||||
b.userMemberMap = make(map[string]*discordgo.Member)
|
b.userMemberMap = make(map[string]*discordgo.Member)
|
||||||
b.channelInfoMap = make(map[string]*config.ChannelInfo)
|
b.channelInfoMap = make(map[string]*config.ChannelInfo)
|
||||||
if b.Config.WebhookURL != "" {
|
if b.GetString("WebhookURL") != "" {
|
||||||
flog.Debug("Configuring Discord Incoming Webhook")
|
b.Log.Debug("Configuring Discord Incoming Webhook")
|
||||||
b.webhookID, b.webhookToken = b.splitURL(b.Config.WebhookURL)
|
b.webhookID, b.webhookToken = b.splitURL(b.GetString("WebhookURL"))
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) Connect() error {
|
func (b *Bdiscord) Connect() error {
|
||||||
var err error
|
var err error
|
||||||
flog.Info("Connecting")
|
var token string
|
||||||
if b.Config.WebhookURL == "" {
|
b.Log.Info("Connecting")
|
||||||
flog.Info("Connecting using token")
|
if b.GetString("WebhookURL") == "" {
|
||||||
|
b.Log.Info("Connecting using token")
|
||||||
} else {
|
} else {
|
||||||
flog.Info("Connecting using webhookurl (for posting) and token")
|
b.Log.Info("Connecting using webhookurl (for posting) and token")
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(b.Config.Token, "Bot ") {
|
if !strings.HasPrefix(b.GetString("Token"), "Bot ") {
|
||||||
b.Config.Token = "Bot " + b.Config.Token
|
token = "Bot " + b.GetString("Token")
|
||||||
}
|
}
|
||||||
b.c, err = discordgo.New(b.Config.Token)
|
b.c, err = discordgo.New(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
b.c.AddHandler(b.messageCreate)
|
b.c.AddHandler(b.messageCreate)
|
||||||
b.c.AddHandler(b.memberUpdate)
|
b.c.AddHandler(b.memberUpdate)
|
||||||
b.c.AddHandler(b.messageUpdate)
|
b.c.AddHandler(b.messageUpdate)
|
||||||
b.c.AddHandler(b.messageDelete)
|
b.c.AddHandler(b.messageDelete)
|
||||||
err = b.c.Open()
|
err = b.c.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
guilds, err := b.c.UserGuilds(100, "", "")
|
guilds, err := b.c.UserGuilds(100, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userinfo, err := b.c.User("@me")
|
userinfo, err := b.c.User("@me")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.Nick = userinfo.Username
|
b.Nick = userinfo.Username
|
||||||
for _, guild := range guilds {
|
for _, guild := range guilds {
|
||||||
if guild.Name == b.Config.Server {
|
if guild.Name == b.GetString("Server") {
|
||||||
b.Channels, err = b.c.GuildChannels(guild.ID)
|
b.Channels, err = b.c.GuildChannels(guild.ID)
|
||||||
b.guildID = guild.ID
|
b.guildID = guild.ID
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, channel := range b.Channels {
|
||||||
|
b.Log.Debugf("found channel %#v", channel)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) Disconnect() error {
|
func (b *Bdiscord) Disconnect() error {
|
||||||
return nil
|
return b.c.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Bdiscord) JoinChannel(channel config.ChannelInfo) error {
|
||||||
b.channelInfoMap[channel.ID] = &channel
|
b.channelInfoMap[channel.ID] = &channel
|
||||||
idcheck := strings.Split(channel.Name, "ID:")
|
idcheck := strings.Split(channel.Name, "ID:")
|
||||||
if len(idcheck) > 1 {
|
if len(idcheck) > 1 {
|
||||||
@@ -105,99 +102,125 @@ func (b *bdiscord) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) Send(msg config.Message) (string, error) {
|
func (b *Bdiscord) Send(msg config.Message) (string, error) {
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
channelID := b.getChannelID(msg.Channel)
|
channelID := b.getChannelID(msg.Channel)
|
||||||
if channelID == "" {
|
if channelID == "" {
|
||||||
flog.Errorf("Could not find channelID for %v", msg.Channel)
|
return "", fmt.Errorf("Could not find channelID for %v", msg.Channel)
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make a action /me of the message
|
||||||
if msg.Event == config.EVENT_USER_ACTION {
|
if msg.Event == config.EVENT_USER_ACTION {
|
||||||
msg.Text = "_" + msg.Text + "_"
|
msg.Text = "_" + msg.Text + "_"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use initial webhook
|
||||||
wID := b.webhookID
|
wID := b.webhookID
|
||||||
wToken := b.webhookToken
|
wToken := b.webhookToken
|
||||||
|
|
||||||
|
// check if have a channel specific webhook
|
||||||
if ci, ok := b.channelInfoMap[msg.Channel+b.Account]; ok {
|
if ci, ok := b.channelInfoMap[msg.Channel+b.Account]; ok {
|
||||||
if ci.Options.WebhookURL != "" {
|
if ci.Options.WebhookURL != "" {
|
||||||
wID, wToken = b.splitURL(ci.Options.WebhookURL)
|
wID, wToken = b.splitURL(ci.Options.WebhookURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if wID == "" {
|
// Use webhook to send the message
|
||||||
flog.Debugf("Broadcasting using token (API)")
|
if wID != "" {
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
// skip events
|
||||||
if msg.ID == "" {
|
if msg.Event != "" && msg.Event != config.EVENT_JOIN_LEAVE && msg.Event != config.EVENT_TOPIC_CHANGE {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
|
||||||
err := b.c.ChannelMessageDelete(channelID, msg.ID)
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
if msg.ID != "" {
|
b.Log.Debugf("Broadcasting using Webhook")
|
||||||
_, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text)
|
for _, f := range msg.Extra["file"] {
|
||||||
return msg.ID, err
|
fi := f.(config.FileInfo)
|
||||||
}
|
if fi.URL != "" {
|
||||||
|
msg.Text += " " + fi.URL
|
||||||
if msg.Extra != nil {
|
|
||||||
// check if we have files to upload (from slack, telegram or mattermost)
|
|
||||||
if len(msg.Extra["file"]) > 0 {
|
|
||||||
var err error
|
|
||||||
for _, f := range msg.Extra["file"] {
|
|
||||||
fi := f.(config.FileInfo)
|
|
||||||
files := []*discordgo.File{}
|
|
||||||
files = append(files, &discordgo.File{fi.Name, "", bytes.NewReader(*fi.Data)})
|
|
||||||
_, err = b.c.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{Content: msg.Username + fi.Comment, Files: files})
|
|
||||||
if err != nil {
|
|
||||||
flog.Errorf("file upload failed: %#v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// skip empty messages
|
||||||
res, err := b.c.ChannelMessageSend(channelID, msg.Username+msg.Text)
|
if msg.Text == "" {
|
||||||
if err != nil {
|
return "", nil
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
return res.ID, err
|
|
||||||
|
msg.Text = helper.ClipMessage(msg.Text, MessageLength)
|
||||||
|
err := b.c.WebhookExecute(
|
||||||
|
wID,
|
||||||
|
wToken,
|
||||||
|
true,
|
||||||
|
&discordgo.WebhookParams{
|
||||||
|
Content: msg.Text,
|
||||||
|
Username: msg.Username,
|
||||||
|
AvatarURL: msg.Avatar,
|
||||||
|
})
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
flog.Debugf("Broadcasting using Webhook")
|
|
||||||
err := b.c.WebhookExecute(
|
b.Log.Debugf("Broadcasting using token (API)")
|
||||||
wID,
|
|
||||||
wToken,
|
// Delete message
|
||||||
true,
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
&discordgo.WebhookParams{
|
if msg.ID == "" {
|
||||||
Content: msg.Text,
|
return "", nil
|
||||||
Username: msg.Username,
|
}
|
||||||
AvatarURL: msg.Avatar,
|
err := b.c.ChannelMessageDelete(channelID, msg.ID)
|
||||||
})
|
return "", err
|
||||||
return "", err
|
}
|
||||||
|
|
||||||
|
// Upload a file if it exists
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
rmsg.Text = helper.ClipMessage(rmsg.Text, MessageLength)
|
||||||
|
b.c.ChannelMessageSend(channelID, rmsg.Username+rmsg.Text)
|
||||||
|
}
|
||||||
|
// check if we have files to upload (from slack, telegram or mattermost)
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
return b.handleUploadFile(&msg, channelID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Text = helper.ClipMessage(msg.Text, MessageLength)
|
||||||
|
// Edit message
|
||||||
|
if msg.ID != "" {
|
||||||
|
_, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text)
|
||||||
|
return msg.ID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post normal message
|
||||||
|
res, err := b.c.ChannelMessageSend(channelID, msg.Username+msg.Text)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return res.ID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) {
|
func (b *Bdiscord) messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) {
|
||||||
rmsg := config.Message{Account: b.Account, ID: m.ID, Event: config.EVENT_MSG_DELETE, Text: config.EVENT_MSG_DELETE}
|
rmsg := config.Message{Account: b.Account, ID: m.ID, Event: config.EVENT_MSG_DELETE, Text: config.EVENT_MSG_DELETE}
|
||||||
rmsg.Channel = b.getChannelName(m.ChannelID)
|
rmsg.Channel = b.getChannelName(m.ChannelID)
|
||||||
if b.UseChannelID {
|
if b.UseChannelID {
|
||||||
rmsg.Channel = "ID:" + m.ChannelID
|
rmsg.Channel = "ID:" + m.ChannelID
|
||||||
}
|
}
|
||||||
flog.Debugf("Sending message from %s to gateway", b.Account)
|
b.Log.Debugf("<= Sending message from %s to gateway", b.Account)
|
||||||
flog.Debugf("Message is %#v", rmsg)
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
b.Remote <- rmsg
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdate) {
|
func (b *Bdiscord) messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdate) {
|
||||||
if b.Config.EditDisable {
|
if b.GetBool("EditDisable") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// only when message is actually edited
|
// only when message is actually edited
|
||||||
if m.Message.EditedTimestamp != "" {
|
if m.Message.EditedTimestamp != "" {
|
||||||
flog.Debugf("Sending edit message")
|
b.Log.Debugf("Sending edit message")
|
||||||
m.Content = m.Content + b.Config.EditSuffix
|
m.Content = m.Content + b.GetString("EditSuffix")
|
||||||
b.messageCreate(s, (*discordgo.MessageCreate)(m))
|
b.messageCreate(s, (*discordgo.MessageCreate)(m))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||||
|
var err error
|
||||||
|
|
||||||
// not relay our own messages
|
// not relay our own messages
|
||||||
if m.Author.Username == b.Nick {
|
if m.Author.Username == b.Nick {
|
||||||
return
|
return
|
||||||
@@ -207,69 +230,73 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add the url of the attachments to content
|
||||||
if len(m.Attachments) > 0 {
|
if len(m.Attachments) > 0 {
|
||||||
for _, attach := range m.Attachments {
|
for _, attach := range m.Attachments {
|
||||||
m.Content = m.Content + "\n" + attach.URL
|
m.Content = m.Content + "\n" + attach.URL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var text string
|
rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", UserID: m.Author.ID, ID: m.ID}
|
||||||
|
|
||||||
if m.Content != "" {
|
if m.Content != "" {
|
||||||
flog.Debugf("Receiving message %#v", m.Message)
|
b.Log.Debugf("== Receiving event %#v", m.Message)
|
||||||
if len(m.MentionRoles) > 0 {
|
|
||||||
m.Message.Content = b.replaceRoleMentions(m.Message.Content)
|
|
||||||
}
|
|
||||||
m.Message.Content = b.stripCustomoji(m.Message.Content)
|
m.Message.Content = b.stripCustomoji(m.Message.Content)
|
||||||
m.Message.Content = b.replaceChannelMentions(m.Message.Content)
|
m.Message.Content = b.replaceChannelMentions(m.Message.Content)
|
||||||
text = m.ContentWithMentionsReplaced()
|
rmsg.Text, err = m.ContentWithMoreMentionsReplaced(b.c)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("ContentWithMoreMentionsReplaced failed: %s", err)
|
||||||
|
rmsg.Text = m.ContentWithMentionsReplaced()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg",
|
// set channel name
|
||||||
UserID: m.Author.ID, ID: m.ID}
|
|
||||||
|
|
||||||
rmsg.Channel = b.getChannelName(m.ChannelID)
|
rmsg.Channel = b.getChannelName(m.ChannelID)
|
||||||
if b.UseChannelID {
|
if b.UseChannelID {
|
||||||
rmsg.Channel = "ID:" + m.ChannelID
|
rmsg.Channel = "ID:" + m.ChannelID
|
||||||
}
|
}
|
||||||
|
|
||||||
if !b.Config.UseUserName {
|
// set username
|
||||||
|
if !b.GetBool("UseUserName") {
|
||||||
rmsg.Username = b.getNick(m.Author)
|
rmsg.Username = b.getNick(m.Author)
|
||||||
} else {
|
} else {
|
||||||
rmsg.Username = m.Author.Username
|
rmsg.Username = m.Author.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Config.ShowEmbeds && m.Message.Embeds != nil {
|
// if we have embedded content add it to text
|
||||||
|
if b.GetBool("ShowEmbeds") && m.Message.Embeds != nil {
|
||||||
for _, embed := range m.Message.Embeds {
|
for _, embed := range m.Message.Embeds {
|
||||||
text = text + "embed: " + embed.Title + " - " + embed.Description + " - " + embed.URL + "\n"
|
rmsg.Text = rmsg.Text + "embed: " + embed.Title + " - " + embed.Description + " - " + embed.URL + "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no empty messages
|
// no empty messages
|
||||||
if text == "" {
|
if rmsg.Text == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
text, ok := b.replaceAction(text)
|
// do we have a /me action
|
||||||
|
var ok bool
|
||||||
|
rmsg.Text, ok = b.replaceAction(rmsg.Text)
|
||||||
if ok {
|
if ok {
|
||||||
rmsg.Event = config.EVENT_USER_ACTION
|
rmsg.Event = config.EVENT_USER_ACTION
|
||||||
}
|
}
|
||||||
|
|
||||||
rmsg.Text = text
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", m.Author.Username, b.Account)
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", m.Author.Username, b.Account)
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
flog.Debugf("Message is %#v", rmsg)
|
|
||||||
b.Remote <- rmsg
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) memberUpdate(s *discordgo.Session, m *discordgo.GuildMemberUpdate) {
|
func (b *Bdiscord) memberUpdate(s *discordgo.Session, m *discordgo.GuildMemberUpdate) {
|
||||||
b.Lock()
|
b.Lock()
|
||||||
if _, ok := b.userMemberMap[m.Member.User.ID]; ok {
|
if _, ok := b.userMemberMap[m.Member.User.ID]; ok {
|
||||||
flog.Debugf("%s: memberupdate: user %s (nick %s) changes nick to %s", b.Account, m.Member.User.Username, b.userMemberMap[m.Member.User.ID].Nick, m.Member.Nick)
|
b.Log.Debugf("%s: memberupdate: user %s (nick %s) changes nick to %s", b.Account, m.Member.User.Username, b.userMemberMap[m.Member.User.ID].Nick, m.Member.Nick)
|
||||||
}
|
}
|
||||||
b.userMemberMap[m.Member.User.ID] = m.Member
|
b.userMemberMap[m.Member.User.ID] = m.Member
|
||||||
b.Unlock()
|
b.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) getNick(user *discordgo.User) string {
|
func (b *Bdiscord) getNick(user *discordgo.User) string {
|
||||||
var err error
|
var err error
|
||||||
b.Lock()
|
b.Lock()
|
||||||
defer b.Unlock()
|
defer b.Unlock()
|
||||||
@@ -296,7 +323,7 @@ func (b *bdiscord) getNick(user *discordgo.User) string {
|
|||||||
return user.Username
|
return user.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) getChannelID(name string) string {
|
func (b *Bdiscord) getChannelID(name string) string {
|
||||||
idcheck := strings.Split(name, "ID:")
|
idcheck := strings.Split(name, "ID:")
|
||||||
if len(idcheck) > 1 {
|
if len(idcheck) > 1 {
|
||||||
return idcheck[1]
|
return idcheck[1]
|
||||||
@@ -309,7 +336,7 @@ func (b *bdiscord) getChannelID(name string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) getChannelName(id string) string {
|
func (b *Bdiscord) getChannelName(id string) string {
|
||||||
for _, channel := range b.Channels {
|
for _, channel := range b.Channels {
|
||||||
if channel.ID == id {
|
if channel.ID == id {
|
||||||
return channel.Name
|
return channel.Name
|
||||||
@@ -318,19 +345,7 @@ func (b *bdiscord) getChannelName(id string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) replaceRoleMentions(text string) string {
|
func (b *Bdiscord) replaceChannelMentions(text string) string {
|
||||||
roles, err := b.c.GuildRoles(b.guildID)
|
|
||||||
if err != nil {
|
|
||||||
flog.Debugf("%#v", string(err.(*discordgo.RESTError).ResponseBody))
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
for _, role := range roles {
|
|
||||||
text = strings.Replace(text, "<@&"+role.ID+">", "@"+role.Name, -1)
|
|
||||||
}
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bdiscord) replaceChannelMentions(text string) string {
|
|
||||||
var err error
|
var err error
|
||||||
re := regexp.MustCompile("<#[0-9]+>")
|
re := regexp.MustCompile("<#[0-9]+>")
|
||||||
text = re.ReplaceAllStringFunc(text, func(m string) string {
|
text = re.ReplaceAllStringFunc(text, func(m string) string {
|
||||||
@@ -349,28 +364,31 @@ func (b *bdiscord) replaceChannelMentions(text string) string {
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) replaceAction(text string) (string, bool) {
|
func (b *Bdiscord) replaceAction(text string) (string, bool) {
|
||||||
if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") {
|
if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") {
|
||||||
return strings.Replace(text, "_", "", -1), true
|
return strings.Replace(text, "_", "", -1), true
|
||||||
}
|
}
|
||||||
return text, false
|
return text, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bdiscord) stripCustomoji(text string) string {
|
func (b *Bdiscord) stripCustomoji(text string) string {
|
||||||
// <:doge:302803592035958784>
|
// <:doge:302803592035958784>
|
||||||
re := regexp.MustCompile("<(:.*?:)[0-9]+>")
|
re := regexp.MustCompile("<(:.*?:)[0-9]+>")
|
||||||
return re.ReplaceAllString(text, `$1`)
|
return re.ReplaceAllString(text, `$1`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// splitURL splits a webhookURL and returns the id and token
|
// 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) {
|
||||||
webhookURLSplit := strings.Split(url, "/")
|
webhookURLSplit := strings.Split(url, "/")
|
||||||
|
if len(webhookURLSplit) != 7 {
|
||||||
|
b.Log.Fatalf("%s is no correct discord WebhookURL", url)
|
||||||
|
}
|
||||||
return webhookURLSplit[len(webhookURLSplit)-2], webhookURLSplit[len(webhookURLSplit)-1]
|
return webhookURLSplit[len(webhookURLSplit)-2], webhookURLSplit[len(webhookURLSplit)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// useWebhook returns true if we have a webhook defined somewhere
|
// useWebhook returns true if we have a webhook defined somewhere
|
||||||
func (b *bdiscord) useWebhook() bool {
|
func (b *Bdiscord) useWebhook() bool {
|
||||||
if b.Config.WebhookURL != "" {
|
if b.GetString("WebhookURL") != "" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for _, channel := range b.channelInfoMap {
|
for _, channel := range b.channelInfoMap {
|
||||||
@@ -382,9 +400,9 @@ func (b *bdiscord) useWebhook() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// isWebhookID returns true if the specified id is used in a defined webhook
|
// isWebhookID returns true if the specified id is used in a defined webhook
|
||||||
func (b *bdiscord) isWebhookID(id string) bool {
|
func (b *Bdiscord) isWebhookID(id string) bool {
|
||||||
if b.Config.WebhookURL != "" {
|
if b.GetString("WebhookURL") != "" {
|
||||||
wID, _ := b.splitURL(b.Config.WebhookURL)
|
wID, _ := b.splitURL(b.GetString("WebhookURL"))
|
||||||
if wID == id {
|
if wID == id {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -399,3 +417,18 @@ func (b *bdiscord) isWebhookID(id string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleUploadFile handles native upload of files
|
||||||
|
func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (string, error) {
|
||||||
|
var err error
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
files := []*discordgo.File{}
|
||||||
|
files = append(files, &discordgo.File{fi.Name, "", bytes.NewReader(*fi.Data)})
|
||||||
|
_, err = b.c.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{Content: msg.Username + fi.Comment, Files: files})
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("file upload failed: %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package bgitter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/go-gitter"
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/42wim/go-gitter"
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bgitter struct {
|
type Bgitter struct {
|
||||||
@@ -13,31 +15,26 @@ type Bgitter struct {
|
|||||||
User *gitter.User
|
User *gitter.User
|
||||||
Users []gitter.User
|
Users []gitter.User
|
||||||
Rooms []gitter.Room
|
Rooms []gitter.Room
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "gitter"
|
return &Bgitter{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Bgitter {
|
|
||||||
return &Bgitter{BridgeConfig: cfg}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bgitter) Connect() error {
|
func (b *Bgitter) Connect() error {
|
||||||
var err error
|
var err error
|
||||||
flog.Info("Connecting")
|
b.Log.Info("Connecting")
|
||||||
b.c = gitter.New(b.Config.Token)
|
b.c = gitter.New(b.GetString("Token"))
|
||||||
b.User, err = b.c.GetUser()
|
b.User, err = b.c.GetUser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flog.Info("Connection succeeded")
|
b.Rooms, err = b.c.GetRooms()
|
||||||
b.Rooms, _ = b.c.GetRooms()
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.Log.Info("Connection succeeded")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +70,9 @@ func (b *Bgitter) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
for event := range stream.Event {
|
for event := range stream.Event {
|
||||||
switch ev := event.Data.(type) {
|
switch ev := event.Data.(type) {
|
||||||
case *gitter.MessageReceived:
|
case *gitter.MessageReceived:
|
||||||
|
// ignore message sent from ourselves
|
||||||
if ev.Message.From.ID != b.User.ID {
|
if ev.Message.From.ID != b.User.ID {
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", ev.Message.From.Username, b.Account)
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", ev.Message.From.Username, b.Account)
|
||||||
rmsg := config.Message{Username: ev.Message.From.Username, Text: ev.Message.Text, Channel: room,
|
rmsg := config.Message{Username: ev.Message.From.Username, Text: ev.Message.Text, Channel: room,
|
||||||
Account: b.Account, Avatar: b.getAvatar(ev.Message.From.Username), UserID: ev.Message.From.ID,
|
Account: b.Account, Avatar: b.getAvatar(ev.Message.From.Username), UserID: ev.Message.From.ID,
|
||||||
ID: ev.Message.ID}
|
ID: ev.Message.ID}
|
||||||
@@ -82,11 +80,11 @@ func (b *Bgitter) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
rmsg.Event = config.EVENT_USER_ACTION
|
rmsg.Event = config.EVENT_USER_ACTION
|
||||||
rmsg.Text = strings.Replace(rmsg.Text, "@"+ev.Message.From.Username+" ", "", -1)
|
rmsg.Text = strings.Replace(rmsg.Text, "@"+ev.Message.From.Username+" ", "", -1)
|
||||||
}
|
}
|
||||||
flog.Debugf("Message is %#v", rmsg)
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
b.Remote <- rmsg
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
case *gitter.GitterConnectionClosed:
|
case *gitter.GitterConnectionClosed:
|
||||||
flog.Errorf("connection with gitter closed for room %s", room)
|
b.Log.Errorf("connection with gitter closed for room %s", room)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(stream, room.URI)
|
}(stream, room.URI)
|
||||||
@@ -94,25 +92,39 @@ func (b *Bgitter) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bgitter) Send(msg config.Message) (string, error) {
|
func (b *Bgitter) Send(msg config.Message) (string, error) {
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
roomID := b.getRoomID(msg.Channel)
|
roomID := b.getRoomID(msg.Channel)
|
||||||
if roomID == "" {
|
if roomID == "" {
|
||||||
flog.Errorf("Could not find roomID for %v", msg.Channel)
|
b.Log.Errorf("Could not find roomID for %v", msg.Channel)
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete message
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
if msg.ID == "" {
|
if msg.ID == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
// gitter has no delete message api
|
// gitter has no delete message api so we edit message to ""
|
||||||
_, err := b.c.UpdateMessage(roomID, msg.ID, "")
|
_, err := b.c.UpdateMessage(roomID, msg.ID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload a file (in gitter case send the upload URL because gitter has no native upload support)
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.c.SendMessage(roomID, rmsg.Username+rmsg.Text)
|
||||||
|
}
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
return b.handleUploadFile(&msg, roomID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit message
|
||||||
if msg.ID != "" {
|
if msg.ID != "" {
|
||||||
flog.Debugf("updating message with id %s", msg.ID)
|
b.Log.Debugf("updating message with id %s", msg.ID)
|
||||||
_, err := b.c.UpdateMessage(roomID, msg.ID, msg.Username+msg.Text)
|
_, err := b.c.UpdateMessage(roomID, msg.ID, msg.Username+msg.Text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -120,22 +132,7 @@ func (b *Bgitter) Send(msg config.Message) (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.Extra != nil {
|
// Post normal message
|
||||||
if len(msg.Extra["file"]) > 0 {
|
|
||||||
for _, f := range msg.Extra["file"] {
|
|
||||||
fi := f.(config.FileInfo)
|
|
||||||
if fi.URL != "" {
|
|
||||||
msg.Text = fi.URL
|
|
||||||
}
|
|
||||||
_, err := b.c.SendMessage(roomID, msg.Username+msg.Text)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := b.c.SendMessage(roomID, msg.Username+msg.Text)
|
resp, err := b.c.SendMessage(roomID, msg.Username+msg.Text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -163,3 +160,23 @@ func (b *Bgitter) getAvatar(user string) string {
|
|||||||
}
|
}
|
||||||
return avatar
|
return avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bgitter) handleUploadFile(msg *config.Message, roomID string) (string, error) {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text += fi.Comment + ": "
|
||||||
|
}
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text = fi.URL
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text = fi.Comment + ": " + fi.URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := b.c.SendMessage(roomID, msg.Username+msg.Text)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,28 +2,41 @@ package helper
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DownloadFile(url string) (*[]byte, error) {
|
func DownloadFile(url string) (*[]byte, error) {
|
||||||
|
return DownloadFileAuth(url, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func DownloadFileAuth(url string, auth string) (*[]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Timeout: time.Second * 5,
|
Timeout: time.Second * 5,
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if auth != "" {
|
||||||
|
req.Header.Add("Authorization", auth)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Body.Close()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
io.Copy(&buf, resp.Body)
|
io.Copy(&buf, resp.Body)
|
||||||
data := buf.Bytes()
|
data := buf.Bytes()
|
||||||
resp.Body.Close()
|
|
||||||
return &data, nil
|
return &data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,3 +51,80 @@ func SplitStringLength(input string, length int) string {
|
|||||||
}
|
}
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle all the stuff we put into extra
|
||||||
|
func HandleExtra(msg *config.Message, general *config.Protocol) []config.Message {
|
||||||
|
extra := msg.Extra
|
||||||
|
rmsg := []config.Message{}
|
||||||
|
if len(extra[config.EVENT_FILE_FAILURE_SIZE]) > 0 {
|
||||||
|
for _, f := range extra[config.EVENT_FILE_FAILURE_SIZE] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
text := fmt.Sprintf("file %s too big to download (%#v > allowed size: %#v)", fi.Name, fi.Size, general.MediaDownloadSize)
|
||||||
|
rmsg = append(rmsg, config.Message{Text: text, Username: "<system> ", Channel: msg.Channel, Account: msg.Account})
|
||||||
|
}
|
||||||
|
return rmsg
|
||||||
|
}
|
||||||
|
return rmsg
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAvatar(av map[string]string, userid string, general *config.Protocol) string {
|
||||||
|
if sha, ok := av[userid]; ok {
|
||||||
|
return general.MediaServerDownload + "/" + sha + "/" + userid + ".png"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleDownloadSize(flog *log.Entry, msg *config.Message, name string, size int64, general *config.Protocol) error {
|
||||||
|
// check blacklist here
|
||||||
|
for _, entry := range general.MediaDownloadBlackList {
|
||||||
|
if entry != "" {
|
||||||
|
re, err := regexp.Compile(entry)
|
||||||
|
if err != nil {
|
||||||
|
flog.Errorf("incorrect regexp %s for %s", entry, msg.Account)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if re.MatchString(name) {
|
||||||
|
return fmt.Errorf("Matching blacklist %s. Not downloading %s", entry, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flog.Debugf("Trying to download %#v with size %#v", name, size)
|
||||||
|
if int(size) > general.MediaDownloadSize {
|
||||||
|
msg.Event = config.EVENT_FILE_FAILURE_SIZE
|
||||||
|
msg.Extra[msg.Event] = append(msg.Extra[msg.Event], config.FileInfo{Name: name, Comment: msg.Text, Size: size})
|
||||||
|
return fmt.Errorf("File %#v to large to download (%#v). MediaDownloadSize is %#v", name, size, general.MediaDownloadSize)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleDownloadData(flog *log.Entry, msg *config.Message, name, comment, url string, data *[]byte, general *config.Protocol) {
|
||||||
|
var avatar bool
|
||||||
|
flog.Debugf("Download OK %#v %#v", name, len(*data))
|
||||||
|
if msg.Event == config.EVENT_AVATAR_DOWNLOAD {
|
||||||
|
avatar = true
|
||||||
|
}
|
||||||
|
msg.Extra["file"] = append(msg.Extra["file"], config.FileInfo{Name: name, Data: data, URL: url, Comment: comment, Avatar: avatar})
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveEmptyNewLines(msg string) string {
|
||||||
|
lines := ""
|
||||||
|
for _, line := range strings.Split(msg, "\n") {
|
||||||
|
if line != "" {
|
||||||
|
lines += line + "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lines = strings.TrimRight(lines, "\n")
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClipMessage(text string, length int) string {
|
||||||
|
// clip too long messages
|
||||||
|
if len(text) > length {
|
||||||
|
text = text[:length-len(" *message clipped*")]
|
||||||
|
if r, size := utf8.DecodeLastRuneInString(text); r == utf8.RuneError {
|
||||||
|
text = text[:len(text)-size]
|
||||||
|
}
|
||||||
|
text += " *message clipped*"
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,13 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"hash/crc32"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/lrstanley/girc"
|
|
||||||
"github.com/paulrosania/go-charset/charset"
|
|
||||||
_ "github.com/paulrosania/go-charset/data"
|
|
||||||
"github.com/saintfish/chardet"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
@@ -19,40 +13,50 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
"github.com/dfordsoft/golib/ic"
|
||||||
|
"github.com/lrstanley/girc"
|
||||||
|
"github.com/paulrosania/go-charset/charset"
|
||||||
|
_ "github.com/paulrosania/go-charset/data"
|
||||||
|
"github.com/saintfish/chardet"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Birc struct {
|
type Birc struct {
|
||||||
i *girc.Client
|
i *girc.Client
|
||||||
Nick string
|
Nick string
|
||||||
names map[string][]string
|
names map[string][]string
|
||||||
connected chan struct{}
|
connected chan struct{}
|
||||||
Local chan config.Message // local queue for flood control
|
Local chan config.Message // local queue for flood control
|
||||||
FirstConnection bool
|
FirstConnection bool
|
||||||
|
MessageDelay, MessageQueue, MessageLength int
|
||||||
|
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "irc"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Birc {
|
|
||||||
b := &Birc{}
|
b := &Birc{}
|
||||||
b.BridgeConfig = cfg
|
b.Config = cfg
|
||||||
b.Nick = b.Config.Nick
|
b.Nick = b.GetString("Nick")
|
||||||
b.names = make(map[string][]string)
|
b.names = make(map[string][]string)
|
||||||
b.connected = make(chan struct{})
|
b.connected = make(chan struct{})
|
||||||
if b.Config.MessageDelay == 0 {
|
if b.GetInt("MessageDelay") == 0 {
|
||||||
b.Config.MessageDelay = 1300
|
b.MessageDelay = 1300
|
||||||
|
} else {
|
||||||
|
b.MessageDelay = b.GetInt("MessageDelay")
|
||||||
}
|
}
|
||||||
if b.Config.MessageQueue == 0 {
|
if b.GetInt("MessageQueue") == 0 {
|
||||||
b.Config.MessageQueue = 30
|
b.MessageQueue = 30
|
||||||
|
} else {
|
||||||
|
b.MessageQueue = b.GetInt("MessageQueue")
|
||||||
}
|
}
|
||||||
if b.Config.MessageLength == 0 {
|
if b.GetInt("MessageLength") == 0 {
|
||||||
b.Config.MessageLength = 400
|
b.MessageLength = 400
|
||||||
|
} else {
|
||||||
|
b.MessageLength = b.GetInt("MessageLength")
|
||||||
}
|
}
|
||||||
b.FirstConnection = true
|
b.FirstConnection = true
|
||||||
return b
|
return b
|
||||||
@@ -69,9 +73,9 @@ func (b *Birc) Command(msg *config.Message) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) Connect() error {
|
func (b *Birc) Connect() error {
|
||||||
b.Local = make(chan config.Message, b.Config.MessageQueue+10)
|
b.Local = make(chan config.Message, b.MessageQueue+10)
|
||||||
flog.Infof("Connecting %s", b.Config.Server)
|
b.Log.Infof("Connecting %s", b.GetString("Server"))
|
||||||
server, portstr, err := net.SplitHostPort(b.Config.Server)
|
server, portstr, err := net.SplitHostPort(b.GetString("Server"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -80,7 +84,7 @@ func (b *Birc) Connect() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// fix strict user handling of girc
|
// fix strict user handling of girc
|
||||||
user := b.Config.Nick
|
user := b.GetString("Nick")
|
||||||
for !girc.IsValidUser(user) {
|
for !girc.IsValidUser(user) {
|
||||||
if len(user) == 1 {
|
if len(user) == 1 {
|
||||||
user = "matterbridge"
|
user = "matterbridge"
|
||||||
@@ -91,62 +95,65 @@ func (b *Birc) Connect() error {
|
|||||||
|
|
||||||
i := girc.New(girc.Config{
|
i := girc.New(girc.Config{
|
||||||
Server: server,
|
Server: server,
|
||||||
ServerPass: b.Config.Password,
|
ServerPass: b.GetString("Password"),
|
||||||
Port: port,
|
Port: port,
|
||||||
Nick: b.Config.Nick,
|
Nick: b.GetString("Nick"),
|
||||||
User: user,
|
User: user,
|
||||||
Name: b.Config.Nick,
|
Name: b.GetString("Nick"),
|
||||||
SSL: b.Config.UseTLS,
|
SSL: b.GetBool("UseTLS"),
|
||||||
TLSConfig: &tls.Config{InsecureSkipVerify: b.Config.SkipTLSVerify, ServerName: server},
|
TLSConfig: &tls.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"), ServerName: server},
|
||||||
PingDelay: time.Minute,
|
PingDelay: time.Minute,
|
||||||
})
|
})
|
||||||
|
|
||||||
if b.Config.UseSASL {
|
if b.GetBool("UseSASL") {
|
||||||
i.Config.SASL = &girc.SASLPlain{b.Config.NickServNick, b.Config.NickServPassword}
|
i.Config.SASL = &girc.SASLPlain{b.GetString("NickServNick"), b.GetString("NickServPassword")}
|
||||||
}
|
}
|
||||||
|
|
||||||
i.Handlers.Add(girc.RPL_WELCOME, b.handleNewConnection)
|
i.Handlers.Add(girc.RPL_WELCOME, b.handleNewConnection)
|
||||||
i.Handlers.Add(girc.RPL_ENDOFMOTD, b.handleOtherAuth)
|
i.Handlers.Add(girc.RPL_ENDOFMOTD, b.handleOtherAuth)
|
||||||
i.Handlers.Add("*", b.handleOther)
|
i.Handlers.Add(girc.ALL_EVENTS, b.handleOther)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if err := i.Connect(); err != nil {
|
if err := i.Connect(); err != nil {
|
||||||
flog.Errorf("error: %s", err)
|
b.Log.Errorf("disconnect: error: %s", err)
|
||||||
flog.Info("reconnecting in 30 seconds...")
|
|
||||||
time.Sleep(30 * time.Second)
|
|
||||||
i.Handlers.Clear(girc.RPL_WELCOME)
|
|
||||||
i.Handlers.Add(girc.RPL_WELCOME, func(client *girc.Client, event girc.Event) {
|
|
||||||
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: "", Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
|
||||||
// set our correct nick on reconnect if necessary
|
|
||||||
b.Nick = event.Source.Name
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
return
|
b.Log.Info("disconnect: client requested quit")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.Log.Info("reconnecting in 30 seconds...")
|
||||||
|
time.Sleep(30 * time.Second)
|
||||||
|
i.Handlers.Clear(girc.RPL_WELCOME)
|
||||||
|
i.Handlers.Add(girc.RPL_WELCOME, func(client *girc.Client, event girc.Event) {
|
||||||
|
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: "", Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
||||||
|
// set our correct nick on reconnect if necessary
|
||||||
|
b.Nick = event.Source.Name
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
b.i = i
|
b.i = i
|
||||||
select {
|
select {
|
||||||
case <-b.connected:
|
case <-b.connected:
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
case <-time.After(time.Second * 30):
|
case <-time.After(time.Second * 30):
|
||||||
return fmt.Errorf("connection timed out")
|
return fmt.Errorf("connection timed out")
|
||||||
}
|
}
|
||||||
//i.Debug = false
|
//i.Debug = false
|
||||||
i.Handlers.Clear("*")
|
if b.GetInt("DebugLevel") == 0 {
|
||||||
|
i.Handlers.Clear(girc.ALL_EVENTS)
|
||||||
|
}
|
||||||
go b.doSend()
|
go b.doSend()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) Disconnect() error {
|
func (b *Birc) Disconnect() error {
|
||||||
//b.i.Disconnect()
|
b.i.Close()
|
||||||
close(b.Local)
|
close(b.Local)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Birc) JoinChannel(channel config.ChannelInfo) error {
|
||||||
if channel.Options.Key != "" {
|
if channel.Options.Key != "" {
|
||||||
flog.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name)
|
b.Log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name)
|
||||||
b.i.Cmd.JoinKey(channel.Name, channel.Options.Key)
|
b.i.Cmd.JoinKey(channel.Name, channel.Options.Key)
|
||||||
} else {
|
} else {
|
||||||
b.i.Cmd.Join(channel.Name)
|
b.i.Cmd.Join(channel.Name)
|
||||||
@@ -159,29 +166,53 @@ func (b *Birc) Send(msg config.Message) (string, error) {
|
|||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
flog.Debugf("Receiving %#v", msg)
|
|
||||||
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
|
// we can be in between reconnects #385
|
||||||
|
if !b.i.IsConnected() {
|
||||||
|
b.Log.Error("Not connected to server, dropping message")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute a command
|
||||||
if strings.HasPrefix(msg.Text, "!") {
|
if strings.HasPrefix(msg.Text, "!") {
|
||||||
b.Command(&msg)
|
b.Command(&msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Config.Charset != "" {
|
// convert to specified charset
|
||||||
buf := new(bytes.Buffer)
|
if b.GetString("Charset") != "" {
|
||||||
w, err := charset.NewWriter(b.Config.Charset, buf)
|
switch b.GetString("Charset") {
|
||||||
if err != nil {
|
case "gbk", "gb18030", "gb2312", "big5", "euc-kr", "euc-jp", "shift-jis", "iso-2022-jp":
|
||||||
flog.Errorf("charset from utf-8 conversion failed: %s", err)
|
msg.Text = ic.ConvertString("utf-8", b.GetString("Charset"), msg.Text)
|
||||||
return "", err
|
default:
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w, err := charset.NewWriter(b.GetString("Charset"), buf)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("charset from utf-8 conversion failed: %s", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, msg.Text)
|
||||||
|
w.Close()
|
||||||
|
msg.Text = buf.String()
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, msg.Text)
|
|
||||||
w.Close()
|
|
||||||
msg.Text = buf.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle files
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.Local <- rmsg
|
||||||
|
}
|
||||||
if len(msg.Extra["file"]) > 0 {
|
if len(msg.Extra["file"]) > 0 {
|
||||||
for _, f := range msg.Extra["file"] {
|
for _, f := range msg.Extra["file"] {
|
||||||
fi := f.(config.FileInfo)
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text += fi.Comment + ": "
|
||||||
|
}
|
||||||
if fi.URL != "" {
|
if fi.URL != "" {
|
||||||
msg.Text = fi.URL
|
msg.Text = fi.URL
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text = fi.Comment + ": " + fi.URL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
b.Local <- config.Message{Text: msg.Text, Username: msg.Username, Channel: msg.Channel, Event: msg.Event}
|
b.Local <- config.Message{Text: msg.Text, Username: msg.Username, Channel: msg.Channel, Event: msg.Event}
|
||||||
}
|
}
|
||||||
@@ -190,35 +221,45 @@ func (b *Birc) Send(msg config.Message) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// split long messages on messageLength, to avoid clipped messages #281
|
// split long messages on messageLength, to avoid clipped messages #281
|
||||||
if b.Config.MessageSplit {
|
if b.GetBool("MessageSplit") {
|
||||||
msg.Text = helper.SplitStringLength(msg.Text, b.Config.MessageLength)
|
msg.Text = helper.SplitStringLength(msg.Text, b.MessageLength)
|
||||||
}
|
}
|
||||||
for _, text := range strings.Split(msg.Text, "\n") {
|
for _, text := range strings.Split(msg.Text, "\n") {
|
||||||
input := []rune(text)
|
if len(text) > b.MessageLength {
|
||||||
if len(text) > b.Config.MessageLength {
|
text = text[:b.MessageLength-len(" <message clipped>")]
|
||||||
text = string(input[:b.Config.MessageLength]) + " <message clipped>"
|
if r, size := utf8.DecodeLastRuneInString(text); r == utf8.RuneError {
|
||||||
|
text = text[:len(text)-size]
|
||||||
|
}
|
||||||
|
text += " <message clipped>"
|
||||||
}
|
}
|
||||||
if len(b.Local) < b.Config.MessageQueue {
|
if len(b.Local) < b.MessageQueue {
|
||||||
if len(b.Local) == b.Config.MessageQueue-1 {
|
if len(b.Local) == b.MessageQueue-1 {
|
||||||
text = text + " <message clipped>"
|
text = text + " <message clipped>"
|
||||||
}
|
}
|
||||||
b.Local <- config.Message{Text: text, Username: msg.Username, Channel: msg.Channel, Event: msg.Event}
|
b.Local <- config.Message{Text: text, Username: msg.Username, Channel: msg.Channel, Event: msg.Event}
|
||||||
} else {
|
} else {
|
||||||
flog.Debugf("flooding, dropping message (queue at %d)", len(b.Local))
|
b.Log.Debugf("flooding, dropping message (queue at %d)", len(b.Local))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) doSend() {
|
func (b *Birc) doSend() {
|
||||||
rate := time.Millisecond * time.Duration(b.Config.MessageDelay)
|
rate := time.Millisecond * time.Duration(b.MessageDelay)
|
||||||
throttle := time.NewTicker(rate)
|
throttle := time.NewTicker(rate)
|
||||||
for msg := range b.Local {
|
for msg := range b.Local {
|
||||||
<-throttle.C
|
<-throttle.C
|
||||||
|
username := msg.Username
|
||||||
|
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)
|
||||||
|
}
|
||||||
if msg.Event == config.EVENT_USER_ACTION {
|
if msg.Event == config.EVENT_USER_ACTION {
|
||||||
b.i.Cmd.Action(msg.Channel, msg.Username+msg.Text)
|
b.i.Cmd.Action(msg.Channel, username+msg.Text)
|
||||||
} else {
|
} else {
|
||||||
b.i.Cmd.Message(msg.Channel, msg.Username+msg.Text)
|
b.Log.Debugf("Sending to channel %s", msg.Channel)
|
||||||
|
b.i.Cmd.Message(msg.Channel, username+msg.Text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +283,7 @@ func (b *Birc) endNames(client *girc.Client, event girc.Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) handleNewConnection(client *girc.Client, event girc.Event) {
|
func (b *Birc) handleNewConnection(client *girc.Client, event girc.Event) {
|
||||||
flog.Debug("Registering callbacks")
|
b.Log.Debug("Registering callbacks")
|
||||||
i := b.i
|
i := b.i
|
||||||
b.Nick = event.Params[0]
|
b.Nick = event.Params[0]
|
||||||
|
|
||||||
@@ -261,107 +302,138 @@ func (b *Birc) handleNewConnection(client *girc.Client, event girc.Event) {
|
|||||||
|
|
||||||
func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) {
|
func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) {
|
||||||
if len(event.Params) == 0 {
|
if len(event.Params) == 0 {
|
||||||
flog.Debugf("handleJoinPart: empty Params? %#v", event)
|
b.Log.Debugf("handleJoinPart: empty Params? %#v", event)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
channel := event.Params[0]
|
channel := strings.ToLower(event.Params[0])
|
||||||
if event.Command == "KICK" {
|
if event.Command == "KICK" && event.Params[1] == b.Nick {
|
||||||
flog.Infof("Got kicked from %s by %s", channel, event.Source.Name)
|
b.Log.Infof("Got kicked from %s by %s", channel, event.Source.Name)
|
||||||
time.Sleep(time.Duration(b.Config.RejoinDelay) * time.Second)
|
time.Sleep(time.Duration(b.GetInt("RejoinDelay")) * time.Second)
|
||||||
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: channel, Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: channel, Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if event.Command == "QUIT" {
|
if event.Command == "QUIT" {
|
||||||
if event.Source.Name == b.Nick && strings.Contains(event.Trailing, "Ping timeout") {
|
if event.Source.Name == b.Nick && strings.Contains(event.Trailing, "Ping timeout") {
|
||||||
flog.Infof("%s reconnecting ..", b.Account)
|
b.Log.Infof("%s reconnecting ..", b.Account)
|
||||||
b.Remote <- config.Message{Username: "system", Text: "reconnect", Channel: channel, Account: b.Account, Event: config.EVENT_FAILURE}
|
b.Remote <- config.Message{Username: "system", Text: "reconnect", Channel: channel, Account: b.Account, Event: config.EVENT_FAILURE}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if event.Source.Name != b.Nick {
|
if event.Source.Name != b.Nick {
|
||||||
flog.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
if b.GetBool("nosendjoinpart") {
|
||||||
b.Remote <- config.Message{Username: "system", Text: event.Source.Name + " " + strings.ToLower(event.Command) + "s", Channel: channel, Account: b.Account, Event: config.EVENT_JOIN_LEAVE}
|
return
|
||||||
|
}
|
||||||
|
b.Log.Debugf("<= Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
||||||
|
msg := config.Message{Username: "system", Text: event.Source.Name + " " + strings.ToLower(event.Command) + "s", Channel: channel, Account: b.Account, Event: config.EVENT_JOIN_LEAVE}
|
||||||
|
b.Log.Debugf("<= Message is %#v", msg)
|
||||||
|
b.Remote <- msg
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
flog.Debugf("handle %#v", event)
|
b.Log.Debugf("handle %#v", event)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) handleNotice(client *girc.Client, event girc.Event) {
|
func (b *Birc) handleNotice(client *girc.Client, event girc.Event) {
|
||||||
if strings.Contains(event.String(), "This nickname is registered") && event.Source.Name == b.Config.NickServNick {
|
if strings.Contains(event.String(), "This nickname is registered") && event.Source.Name == b.GetString("NickServNick") {
|
||||||
b.i.Cmd.Message(b.Config.NickServNick, "IDENTIFY "+b.Config.NickServPassword)
|
b.Log.Debugf("Sending identify to nickserv %s", b.GetString("NickServNick"))
|
||||||
|
b.i.Cmd.Message(b.GetString("NickServNick"), "IDENTIFY "+b.GetString("NickServPassword"))
|
||||||
} else {
|
} else {
|
||||||
b.handlePrivMsg(client, event)
|
b.handlePrivMsg(client, event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) handleOther(client *girc.Client, event girc.Event) {
|
func (b *Birc) handleOther(client *girc.Client, event girc.Event) {
|
||||||
|
if b.GetInt("DebugLevel") == 1 {
|
||||||
|
if event.Command != "CLIENT_STATE_UPDATED" &&
|
||||||
|
event.Command != "CLIENT_GENERAL_UPDATED" {
|
||||||
|
b.Log.Debugf("%#v", event.String())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
switch event.Command {
|
switch event.Command {
|
||||||
case "372", "375", "376", "250", "251", "252", "253", "254", "255", "265", "266", "002", "003", "004", "005":
|
case "372", "375", "376", "250", "251", "252", "253", "254", "255", "265", "266", "002", "003", "004", "005":
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
flog.Debugf("%#v", event.String())
|
b.Log.Debugf("%#v", event.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) handleOtherAuth(client *girc.Client, event girc.Event) {
|
func (b *Birc) handleOtherAuth(client *girc.Client, event girc.Event) {
|
||||||
if strings.EqualFold(b.Config.NickServNick, "Q@CServe.quakenet.org") {
|
if strings.EqualFold(b.GetString("NickServNick"), "Q@CServe.quakenet.org") {
|
||||||
flog.Debugf("Authenticating %s against %s", b.Config.NickServUsername, b.Config.NickServNick)
|
b.Log.Debugf("Authenticating %s against %s", b.GetString("NickServUsername"), b.GetString("NickServNick"))
|
||||||
b.i.Cmd.Message(b.Config.NickServNick, "AUTH "+b.Config.NickServUsername+" "+b.Config.NickServPassword)
|
b.i.Cmd.Message(b.GetString("NickServNick"), "AUTH "+b.GetString("NickServUsername")+" "+b.GetString("NickServPassword"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) {
|
func (b *Birc) skipPrivMsg(event girc.Event) bool {
|
||||||
|
// Our nick can be changed
|
||||||
b.Nick = b.i.GetNick()
|
b.Nick = b.i.GetNick()
|
||||||
|
|
||||||
// freenode doesn't send 001 as first reply
|
// freenode doesn't send 001 as first reply
|
||||||
if event.Command == "NOTICE" {
|
if event.Command == "NOTICE" {
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
// don't forward queries to the bot
|
// don't forward queries to the bot
|
||||||
if event.Params[0] == b.Nick {
|
if event.Params[0] == b.Nick {
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
// don't forward message from ourself
|
// don't forward message from ourself
|
||||||
if event.Source.Name == b.Nick {
|
if event.Source.Name == b.Nick {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) {
|
||||||
|
if b.skipPrivMsg(event) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rmsg := config.Message{Username: event.Source.Name, Channel: 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}
|
||||||
flog.Debugf("handlePrivMsg() %s %s %#v", event.Source.Name, event.Trailing, event)
|
b.Log.Debugf("== Receiving PRIVMSG: %s %s %#v", event.Source.Name, event.Trailing, event)
|
||||||
msg := ""
|
|
||||||
|
// set action event
|
||||||
if event.IsAction() {
|
if event.IsAction() {
|
||||||
rmsg.Event = config.EVENT_USER_ACTION
|
rmsg.Event = config.EVENT_USER_ACTION
|
||||||
}
|
}
|
||||||
msg += event.StripAction()
|
|
||||||
// strip IRC colors
|
|
||||||
re := regexp.MustCompile(`[[:cntrl:]](?:\d{1,2}(?:,\d{1,2})?)?`)
|
|
||||||
msg = re.ReplaceAllString(msg, "")
|
|
||||||
|
|
||||||
|
// strip action, we made an event if it was an action
|
||||||
|
rmsg.Text += event.StripAction()
|
||||||
|
|
||||||
|
// strip IRC colors
|
||||||
|
re := regexp.MustCompile(`\x03(?:\d{1,2}(?:,\d{1,2})?)?|[[:cntrl:]]`)
|
||||||
|
rmsg.Text = re.ReplaceAllString(rmsg.Text, "")
|
||||||
|
|
||||||
|
// start detecting the charset
|
||||||
var r io.Reader
|
var r io.Reader
|
||||||
var err error
|
var err error
|
||||||
mycharset := b.Config.Charset
|
mycharset := b.GetString("Charset")
|
||||||
if mycharset == "" {
|
if mycharset == "" {
|
||||||
// detect what were sending so that we convert it to utf-8
|
// detect what were sending so that we convert it to utf-8
|
||||||
detector := chardet.NewTextDetector()
|
detector := chardet.NewTextDetector()
|
||||||
result, err := detector.DetectBest([]byte(msg))
|
result, err := detector.DetectBest([]byte(rmsg.Text))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Infof("detection failed for msg: %#v", msg)
|
b.Log.Infof("detection failed for rmsg.Text: %#v", rmsg.Text)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
flog.Debugf("detected %s confidence %#v", result.Charset, result.Confidence)
|
b.Log.Debugf("detected %s confidence %#v", result.Charset, result.Confidence)
|
||||||
mycharset = result.Charset
|
mycharset = result.Charset
|
||||||
// if we're not sure, just pick ISO-8859-1
|
// if we're not sure, just pick ISO-8859-1
|
||||||
if result.Confidence < 80 {
|
if result.Confidence < 80 {
|
||||||
mycharset = "ISO-8859-1"
|
mycharset = "ISO-8859-1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r, err = charset.NewReader(mycharset, strings.NewReader(msg))
|
switch mycharset {
|
||||||
if err != nil {
|
case "gbk", "gb18030", "gb2312", "big5", "euc-kr", "euc-jp", "shift-jis", "iso-2022-jp":
|
||||||
flog.Errorf("charset to utf-8 conversion failed: %s", err)
|
rmsg.Text = ic.ConvertString("utf-8", b.GetString("Charset"), rmsg.Text)
|
||||||
return
|
default:
|
||||||
|
r, err = charset.NewReader(mycharset, strings.NewReader(rmsg.Text))
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("charset to utf-8 conversion failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output, _ := ioutil.ReadAll(r)
|
||||||
|
rmsg.Text = string(output)
|
||||||
}
|
}
|
||||||
output, _ := ioutil.ReadAll(r)
|
|
||||||
msg = string(output)
|
|
||||||
|
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", event.Params[0], b.Account)
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", event.Params[0], b.Account)
|
||||||
rmsg.Text = msg
|
|
||||||
b.Remote <- rmsg
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,13 +441,13 @@ func (b *Birc) handleTopicWhoTime(client *girc.Client, event girc.Event) {
|
|||||||
parts := strings.Split(event.Params[2], "!")
|
parts := strings.Split(event.Params[2], "!")
|
||||||
t, err := strconv.ParseInt(event.Params[3], 10, 64)
|
t, err := strconv.ParseInt(event.Params[3], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Errorf("Invalid time stamp: %s", event.Params[3])
|
b.Log.Errorf("Invalid time stamp: %s", event.Params[3])
|
||||||
}
|
}
|
||||||
user := parts[0]
|
user := parts[0]
|
||||||
if len(parts) > 1 {
|
if len(parts) > 1 {
|
||||||
user += " [" + parts[1] + "]"
|
user += " [" + parts[1] + "]"
|
||||||
}
|
}
|
||||||
flog.Debugf("%s: Topic set by %s [%s]", event.Command, user, time.Unix(t, 0))
|
b.Log.Debugf("%s: Topic set by %s [%s]", event.Command, user, time.Unix(t, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) nicksPerRow() int {
|
func (b *Birc) nicksPerRow() int {
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package bmatrix
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"mime"
|
"mime"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
log "github.com/Sirupsen/logrus"
|
matrix "github.com/matterbridge/gomatrix"
|
||||||
matrix "github.com/matrix-org/gomatrix"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bmatrix struct {
|
type Bmatrix struct {
|
||||||
@@ -18,42 +19,33 @@ type Bmatrix struct {
|
|||||||
UserID string
|
UserID string
|
||||||
RoomMap map[string]string
|
RoomMap map[string]string
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "matrix"
|
b := &Bmatrix{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Bmatrix {
|
|
||||||
b := &Bmatrix{BridgeConfig: cfg}
|
|
||||||
b.RoomMap = make(map[string]string)
|
b.RoomMap = make(map[string]string)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmatrix) Connect() error {
|
func (b *Bmatrix) Connect() error {
|
||||||
var err error
|
var err error
|
||||||
flog.Infof("Connecting %s", b.Config.Server)
|
b.Log.Infof("Connecting %s", b.GetString("Server"))
|
||||||
b.mc, err = matrix.NewClient(b.Config.Server, "", "")
|
b.mc, err = matrix.NewClient(b.GetString("Server"), "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resp, err := b.mc.Login(&matrix.ReqLogin{
|
resp, err := b.mc.Login(&matrix.ReqLogin{
|
||||||
Type: "m.login.password",
|
Type: "m.login.password",
|
||||||
User: b.Config.Login,
|
User: b.GetString("Login"),
|
||||||
Password: b.Config.Password,
|
Password: b.GetString("Password"),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.mc.SetCredentials(resp.UserID, resp.AccessToken)
|
b.mc.SetCredentials(resp.UserID, resp.AccessToken)
|
||||||
b.UserID = resp.UserID
|
b.UserID = resp.UserID
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
go b.handlematrix()
|
go b.handlematrix()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -74,58 +66,53 @@ func (b *Bmatrix) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmatrix) Send(msg config.Message) (string, error) {
|
func (b *Bmatrix) Send(msg config.Message) (string, error) {
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
// ignore delete messages
|
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
channel := b.getRoomID(msg.Channel)
|
channel := b.getRoomID(msg.Channel)
|
||||||
flog.Debugf("Sending to channel %s", channel)
|
b.Log.Debugf("Channel %s maps to channel id %s", msg.Channel, channel)
|
||||||
|
|
||||||
|
// Make a action /me of the message
|
||||||
if msg.Event == config.EVENT_USER_ACTION {
|
if msg.Event == config.EVENT_USER_ACTION {
|
||||||
b.mc.SendMessageEvent(channel, "m.room.message",
|
resp, err := b.mc.SendMessageEvent(channel, "m.room.message",
|
||||||
matrix.TextMessage{"m.emote", msg.Username + msg.Text})
|
matrix.TextMessage{"m.emote", msg.Username + msg.Text})
|
||||||
return "", nil
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return resp.EventID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete message
|
||||||
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
|
if msg.ID == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
resp, err := b.mc.RedactEvent(channel, msg.ID, &matrix.ReqRedact{})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return resp.EventID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload a file if it exists
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.mc.SendText(channel, rmsg.Username+rmsg.Text)
|
||||||
|
}
|
||||||
// check if we have files to upload (from slack, telegram or mattermost)
|
// check if we have files to upload (from slack, telegram or mattermost)
|
||||||
if len(msg.Extra["file"]) > 0 {
|
if len(msg.Extra["file"]) > 0 {
|
||||||
for _, f := range msg.Extra["file"] {
|
return b.handleUploadFile(&msg, channel)
|
||||||
fi := f.(config.FileInfo)
|
|
||||||
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") {
|
|
||||||
flog.Debugf("uploading file: %s %s", fi.Name, mtype)
|
|
||||||
res, err := b.mc.UploadToContentRepo(content, mtype, int64(len(*fi.Data)))
|
|
||||||
if err != nil {
|
|
||||||
flog.Errorf("file upload failed: %#v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.Contains(mtype, "video") {
|
|
||||||
flog.Debugf("sendVideo %s", res.ContentURI)
|
|
||||||
_, err = b.mc.SendVideo(channel, fi.Name, res.ContentURI)
|
|
||||||
if err != nil {
|
|
||||||
flog.Errorf("sendVideo failed: %#v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.Contains(mtype, "image") {
|
|
||||||
flog.Debugf("sendImage %s", res.ContentURI)
|
|
||||||
_, err = b.mc.SendImage(channel, fi.Name, res.ContentURI)
|
|
||||||
if err != nil {
|
|
||||||
flog.Errorf("sendImage failed: %#v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flog.Debugf("result: %#v", res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b.mc.SendText(channel, msg.Username+msg.Text)
|
// Edit message if we have an ID
|
||||||
return "", nil
|
// matrix has no editing support
|
||||||
|
|
||||||
|
// Post normal message
|
||||||
|
resp, err := b.mc.SendText(channel, msg.Username+msg.Text)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return resp.EventID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmatrix) getRoomID(channel string) string {
|
func (b *Bmatrix) getRoomID(channel string) string {
|
||||||
@@ -138,64 +125,188 @@ func (b *Bmatrix) getRoomID(channel string) string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmatrix) handlematrix() error {
|
func (b *Bmatrix) handlematrix() error {
|
||||||
syncer := b.mc.Syncer.(*matrix.DefaultSyncer)
|
syncer := b.mc.Syncer.(*matrix.DefaultSyncer)
|
||||||
syncer.OnEventType("m.room.message", func(ev *matrix.Event) {
|
syncer.OnEventType("m.room.redaction", b.handleEvent)
|
||||||
flog.Debugf("Received: %#v", ev)
|
syncer.OnEventType("m.room.message", b.handleEvent)
|
||||||
if (ev.Content["msgtype"].(string) == "m.text" ||
|
|
||||||
ev.Content["msgtype"].(string) == "m.notice" ||
|
|
||||||
ev.Content["msgtype"].(string) == "m.emote" ||
|
|
||||||
ev.Content["msgtype"].(string) == "m.file" ||
|
|
||||||
ev.Content["msgtype"].(string) == "m.image" ||
|
|
||||||
ev.Content["msgtype"].(string) == "m.video") && ev.Sender != b.UserID {
|
|
||||||
b.RLock()
|
|
||||||
channel, ok := b.RoomMap[ev.RoomID]
|
|
||||||
b.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
flog.Debugf("Unknown room %s", ev.RoomID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
username := ev.Sender[1:]
|
|
||||||
if b.Config.NoHomeServerSuffix {
|
|
||||||
re := regexp.MustCompile("(.*?):.*")
|
|
||||||
username = re.ReplaceAllString(username, `$1`)
|
|
||||||
}
|
|
||||||
rmsg := config.Message{Username: username, Text: ev.Content["body"].(string), Channel: channel, Account: b.Account, UserID: ev.Sender}
|
|
||||||
if ev.Content["msgtype"].(string) == "m.emote" {
|
|
||||||
rmsg.Event = config.EVENT_USER_ACTION
|
|
||||||
}
|
|
||||||
if ev.Content["msgtype"].(string) == "m.image" ||
|
|
||||||
ev.Content["msgtype"].(string) == "m.video" ||
|
|
||||||
ev.Content["msgtype"].(string) == "m.file" {
|
|
||||||
flog.Debugf("ev: %#v", ev)
|
|
||||||
rmsg.Extra = make(map[string][]interface{})
|
|
||||||
url := ev.Content["url"].(string)
|
|
||||||
url = strings.Replace(url, "mxc://", b.Config.Server+"/_matrix/media/v1/download/", -1)
|
|
||||||
info := ev.Content["info"].(map[string]interface{})
|
|
||||||
size := info["size"].(float64)
|
|
||||||
name := ev.Content["body"].(string)
|
|
||||||
flog.Debugf("trying to download %#v with size %#v", name, size)
|
|
||||||
if size <= float64(b.General.MediaDownloadSize) {
|
|
||||||
data, err := helper.DownloadFile(url)
|
|
||||||
if err != nil {
|
|
||||||
flog.Errorf("download %s failed %#v", url, err)
|
|
||||||
} else {
|
|
||||||
flog.Debugf("download OK %#v %#v %#v", name, len(*data), len(url))
|
|
||||||
rmsg.Extra["file"] = append(rmsg.Extra["file"], config.FileInfo{Name: name, Data: data})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rmsg.Text = ""
|
|
||||||
}
|
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", ev.Sender, b.Account)
|
|
||||||
b.Remote <- rmsg
|
|
||||||
}
|
|
||||||
})
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if err := b.mc.Sync(); err != nil {
|
if err := b.mc.Sync(); err != nil {
|
||||||
flog.Println("Sync() returned ", err)
|
b.Log.Println("Sync() returned ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bmatrix) handleEvent(ev *matrix.Event) {
|
||||||
|
b.Log.Debugf("== Receiving event: %#v", ev)
|
||||||
|
if ev.Sender != b.UserID {
|
||||||
|
b.RLock()
|
||||||
|
channel, ok := b.RoomMap[ev.RoomID]
|
||||||
|
b.RUnlock()
|
||||||
|
if !ok {
|
||||||
|
b.Log.Debugf("Unknown room %s", ev.RoomID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO download avatar
|
||||||
|
|
||||||
|
// Create our message
|
||||||
|
rmsg := config.Message{Username: ev.Sender[1:], Channel: channel, Account: b.Account, UserID: ev.Sender, ID: ev.ID}
|
||||||
|
|
||||||
|
// Text must be a string
|
||||||
|
if rmsg.Text, ok = ev.Content["body"].(string); !ok {
|
||||||
|
b.Log.Errorf("Content[body] wasn't a %T ?", rmsg.Text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove homeserver suffix if configured
|
||||||
|
if b.GetBool("NoHomeServerSuffix") {
|
||||||
|
re := regexp.MustCompile("(.*?):.*")
|
||||||
|
rmsg.Username = re.ReplaceAllString(rmsg.Username, `$1`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete event
|
||||||
|
if ev.Type == "m.room.redaction" {
|
||||||
|
rmsg.Event = config.EVENT_MSG_DELETE
|
||||||
|
rmsg.ID = ev.Redacts
|
||||||
|
rmsg.Text = config.EVENT_MSG_DELETE
|
||||||
|
b.Remote <- rmsg
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have a /me action
|
||||||
|
if ev.Content["msgtype"].(string) == "m.emote" {
|
||||||
|
rmsg.Event = config.EVENT_USER_ACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have attachments
|
||||||
|
if b.containsAttachment(ev.Content) {
|
||||||
|
err := b.handleDownloadFile(&rmsg, ev.Content)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("download failed: %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", ev.Sender, b.Account)
|
||||||
|
b.Remote <- rmsg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleDownloadFile handles file download
|
||||||
|
func (b *Bmatrix) handleDownloadFile(rmsg *config.Message, content map[string]interface{}) error {
|
||||||
|
var (
|
||||||
|
ok bool
|
||||||
|
url, name, msgtype, mtype string
|
||||||
|
info map[string]interface{}
|
||||||
|
size float64
|
||||||
|
)
|
||||||
|
|
||||||
|
rmsg.Extra = make(map[string][]interface{})
|
||||||
|
if url, ok = content["url"].(string); !ok {
|
||||||
|
return fmt.Errorf("url isn't a %T", url)
|
||||||
|
}
|
||||||
|
url = strings.Replace(url, "mxc://", b.GetString("Server")+"/_matrix/media/v1/download/", -1)
|
||||||
|
|
||||||
|
if info, ok = content["info"].(map[string]interface{}); !ok {
|
||||||
|
return fmt.Errorf("info isn't a %T", info)
|
||||||
|
}
|
||||||
|
if size, ok = info["size"].(float64); !ok {
|
||||||
|
return fmt.Errorf("size isn't a %T", size)
|
||||||
|
}
|
||||||
|
if name, ok = content["body"].(string); !ok {
|
||||||
|
return fmt.Errorf("name isn't a %T", name)
|
||||||
|
}
|
||||||
|
if msgtype, ok = content["msgtype"].(string); !ok {
|
||||||
|
return fmt.Errorf("msgtype isn't a %T", msgtype)
|
||||||
|
}
|
||||||
|
if mtype, ok = info["mimetype"].(string); !ok {
|
||||||
|
return fmt.Errorf("mtype isn't a %T", mtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we have an image uploaded without extension
|
||||||
|
if !strings.Contains(name, ".") {
|
||||||
|
if msgtype == "m.image" {
|
||||||
|
mext, _ := mime.ExtensionsByType(mtype)
|
||||||
|
if len(mext) > 0 {
|
||||||
|
name = name + mext[0]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// just a default .png extension if we don't have mime info
|
||||||
|
name = name + ".png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the size is ok
|
||||||
|
err := helper.HandleDownloadSize(b.Log, rmsg, name, int64(size), b.General)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// actually download the file
|
||||||
|
data, err := helper.DownloadFile(url)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("download %s failed %#v", url, err)
|
||||||
|
}
|
||||||
|
// add the downloaded data to the message
|
||||||
|
helper.HandleDownloadData(b.Log, rmsg, name, "", url, data, b.General)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleUploadFile handles native upload of files
|
||||||
|
func (b *Bmatrix) handleUploadFile(msg *config.Message, channel string) (string, error) {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
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") {
|
||||||
|
if fi.Comment != "" {
|
||||||
|
_, err := b.mc.SendText(channel, msg.Username+fi.Comment)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("file comment failed: %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Log.Debugf("uploading file: %s %s", fi.Name, mtype)
|
||||||
|
res, err := b.mc.UploadToContentRepo(content, mtype, int64(len(*fi.Data)))
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("file upload failed: %#v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(mtype, "video") {
|
||||||
|
b.Log.Debugf("sendVideo %s", res.ContentURI)
|
||||||
|
_, err = b.mc.SendVideo(channel, fi.Name, res.ContentURI)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("sendVideo failed: %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.Contains(mtype, "image") {
|
||||||
|
b.Log.Debugf("sendImage %s", res.ContentURI)
|
||||||
|
_, err = b.mc.SendImage(channel, fi.Name, res.ContentURI)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("sendImage failed: %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Log.Debugf("result: %#v", res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,52 +3,28 @@ package bmattermost
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/42wim/matterbridge/matterclient"
|
"github.com/42wim/matterbridge/matterclient"
|
||||||
"github.com/42wim/matterbridge/matterhook"
|
"github.com/42wim/matterbridge/matterhook"
|
||||||
log "github.com/Sirupsen/logrus"
|
"github.com/rs/xid"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MMhook struct {
|
|
||||||
mh *matterhook.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
type MMapi struct {
|
|
||||||
mc *matterclient.MMClient
|
|
||||||
mmMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
type MMMessage struct {
|
|
||||||
Text string
|
|
||||||
Channel string
|
|
||||||
Username string
|
|
||||||
UserID string
|
|
||||||
ID string
|
|
||||||
Event string
|
|
||||||
Extra map[string][]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Bmattermost struct {
|
type Bmattermost struct {
|
||||||
MMhook
|
mh *matterhook.Client
|
||||||
MMapi
|
mc *matterclient.MMClient
|
||||||
Config *config.Protocol
|
uuid string
|
||||||
Remote chan config.Message
|
TeamID string
|
||||||
TeamId string
|
*bridge.Config
|
||||||
Account string
|
avatarMap map[string]string
|
||||||
*config.BridgeConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "mattermost"
|
b := &Bmattermost{Config: cfg, avatarMap: make(map[string]string)}
|
||||||
|
b.uuid = xid.New().String()
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Bmattermost {
|
|
||||||
b := &Bmattermost{BridgeConfig: cfg}
|
|
||||||
b.mmMap = make(map[string]string)
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,47 +33,47 @@ func (b *Bmattermost) Command(cmd string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmattermost) Connect() error {
|
func (b *Bmattermost) Connect() error {
|
||||||
if b.Config.WebhookBindAddress != "" {
|
if b.GetString("WebhookBindAddress") != "" {
|
||||||
if b.Config.WebhookURL != "" {
|
if b.GetString("WebhookURL") != "" {
|
||||||
flog.Info("Connecting using webhookurl (sending) and webhookbindaddress (receiving)")
|
b.Log.Info("Connecting using webhookurl (sending) and webhookbindaddress (receiving)")
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
BindAddress: b.Config.WebhookBindAddress})
|
BindAddress: b.GetString("WebhookBindAddress")})
|
||||||
} else if b.Config.Token != "" {
|
} else if b.GetString("Token") != "" {
|
||||||
flog.Info("Connecting using token (sending)")
|
b.Log.Info("Connecting using token (sending)")
|
||||||
err := b.apiLogin()
|
err := b.apiLogin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if b.Config.Login != "" {
|
} else if b.GetString("Login") != "" {
|
||||||
flog.Info("Connecting using login/password (sending)")
|
b.Log.Info("Connecting using login/password (sending)")
|
||||||
err := b.apiLogin()
|
err := b.apiLogin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
flog.Info("Connecting using webhookbindaddress (receiving)")
|
b.Log.Info("Connecting using webhookbindaddress (receiving)")
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
BindAddress: b.Config.WebhookBindAddress})
|
BindAddress: b.GetString("WebhookBindAddress")})
|
||||||
}
|
}
|
||||||
go b.handleMatter()
|
go b.handleMatter()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if b.Config.WebhookURL != "" {
|
if b.GetString("WebhookURL") != "" {
|
||||||
flog.Info("Connecting using webhookurl (sending)")
|
b.Log.Info("Connecting using webhookurl (sending)")
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
DisableServer: true})
|
DisableServer: true})
|
||||||
if b.Config.Token != "" {
|
if b.GetString("Token") != "" {
|
||||||
flog.Info("Connecting using token (receiving)")
|
b.Log.Info("Connecting using token (receiving)")
|
||||||
err := b.apiLogin()
|
err := b.apiLogin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go b.handleMatter()
|
go b.handleMatter()
|
||||||
} else if b.Config.Login != "" {
|
} else if b.GetString("Login") != "" {
|
||||||
flog.Info("Connecting using login/password (receiving)")
|
b.Log.Info("Connecting using login/password (receiving)")
|
||||||
err := b.apiLogin()
|
err := b.apiLogin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -105,23 +81,23 @@ func (b *Bmattermost) Connect() error {
|
|||||||
go b.handleMatter()
|
go b.handleMatter()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
} else if b.Config.Token != "" {
|
} else if b.GetString("Token") != "" {
|
||||||
flog.Info("Connecting using token (sending and receiving)")
|
b.Log.Info("Connecting using token (sending and receiving)")
|
||||||
err := b.apiLogin()
|
err := b.apiLogin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go b.handleMatter()
|
go b.handleMatter()
|
||||||
} else if b.Config.Login != "" {
|
} else if b.GetString("Login") != "" {
|
||||||
flog.Info("Connecting using login/password (sending and receiving)")
|
b.Log.Info("Connecting using login/password (sending and receiving)")
|
||||||
err := b.apiLogin()
|
err := b.apiLogin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go b.handleMatter()
|
go b.handleMatter()
|
||||||
}
|
}
|
||||||
if b.Config.WebhookBindAddress == "" && b.Config.WebhookURL == "" && b.Config.Login == "" && b.Config.Token == "" {
|
if b.GetString("WebhookBindAddress") == "" && b.GetString("WebhookURL") == "" && b.GetString("Login") == "" && b.GetString("Token") == "" {
|
||||||
return errors.New("No connection method found. See that you have WebhookBindAddress, WebhookURL or Token/Login/Password/Server/Team configured.")
|
return errors.New("no connection method found. See that you have WebhookBindAddress, WebhookURL or Token/Login/Password/Server/Team configured")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -132,7 +108,7 @@ func (b *Bmattermost) Disconnect() error {
|
|||||||
|
|
||||||
func (b *Bmattermost) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Bmattermost) JoinChannel(channel config.ChannelInfo) error {
|
||||||
// we can only join channels using the API
|
// we can only join channels using the API
|
||||||
if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" {
|
if b.GetString("WebhookURL") == "" && b.GetString("WebhookBindAddress") == "" {
|
||||||
id := b.mc.GetChannelId(channel.Name, "")
|
id := b.mc.GetChannelId(channel.Name, "")
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return fmt.Errorf("Could not find channel ID for channel %s", channel.Name)
|
return fmt.Errorf("Could not find channel ID for channel %s", channel.Name)
|
||||||
@@ -143,189 +119,349 @@ func (b *Bmattermost) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmattermost) Send(msg config.Message) (string, error) {
|
func (b *Bmattermost) Send(msg config.Message) (string, error) {
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
|
// Make a action /me of the message
|
||||||
if msg.Event == config.EVENT_USER_ACTION {
|
if msg.Event == config.EVENT_USER_ACTION {
|
||||||
msg.Text = "*" + msg.Text + "*"
|
msg.Text = "*" + msg.Text + "*"
|
||||||
}
|
}
|
||||||
nick := msg.Username
|
|
||||||
message := msg.Text
|
|
||||||
channel := msg.Channel
|
|
||||||
|
|
||||||
if b.Config.PrefixMessagesWithNick {
|
// map the file SHA to our user (caches the avatar)
|
||||||
message = nick + message
|
if msg.Event == config.EVENT_AVATAR_DOWNLOAD {
|
||||||
|
return b.cacheAvatar(&msg)
|
||||||
}
|
}
|
||||||
if b.Config.WebhookURL != "" {
|
|
||||||
matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL}
|
// Use webhook to send the message
|
||||||
matterMessage.IconURL = msg.Avatar
|
if b.GetString("WebhookURL") != "" {
|
||||||
matterMessage.Channel = channel
|
return b.sendWebhook(msg)
|
||||||
matterMessage.UserName = nick
|
|
||||||
matterMessage.Type = ""
|
|
||||||
matterMessage.Text = message
|
|
||||||
matterMessage.Text = message
|
|
||||||
matterMessage.Props = make(map[string]interface{})
|
|
||||||
matterMessage.Props["matterbridge"] = true
|
|
||||||
err := b.mh.Send(matterMessage)
|
|
||||||
if err != nil {
|
|
||||||
flog.Info(err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete message
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
if msg.ID == "" {
|
if msg.ID == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return msg.ID, b.mc.DeleteMessage(msg.ID)
|
return msg.ID, b.mc.DeleteMessage(msg.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload a file if it exists
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.mc.PostMessage(b.mc.GetChannelId(rmsg.Channel, ""), rmsg.Username+rmsg.Text)
|
||||||
|
}
|
||||||
if len(msg.Extra["file"]) > 0 {
|
if len(msg.Extra["file"]) > 0 {
|
||||||
var err error
|
return b.handleUploadFile(&msg)
|
||||||
var res, id string
|
|
||||||
for _, f := range msg.Extra["file"] {
|
|
||||||
fi := f.(config.FileInfo)
|
|
||||||
id, err = b.mc.UploadFile(*fi.Data, b.mc.GetChannelId(channel, ""), fi.Name)
|
|
||||||
if err != nil {
|
|
||||||
flog.Debugf("ERROR %#v", err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
message = fi.Comment
|
|
||||||
if b.Config.PrefixMessagesWithNick {
|
|
||||||
message = nick + fi.Comment
|
|
||||||
}
|
|
||||||
res, err = b.mc.PostMessageWithFiles(b.mc.GetChannelId(channel, ""), message, []string{id})
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if msg.ID != "" {
|
|
||||||
return b.mc.EditMessage(msg.ID, message)
|
// Prepend nick if configured
|
||||||
|
if b.GetBool("PrefixMessagesWithNick") {
|
||||||
|
msg.Text = msg.Username + msg.Text
|
||||||
}
|
}
|
||||||
return b.mc.PostMessage(b.mc.GetChannelId(channel, ""), message)
|
|
||||||
|
// Edit message if we have an ID
|
||||||
|
if msg.ID != "" {
|
||||||
|
return b.mc.EditMessage(msg.ID, msg.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post normal message
|
||||||
|
return b.mc.PostMessage(b.mc.GetChannelId(msg.Channel, ""), msg.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmattermost) handleMatter() {
|
func (b *Bmattermost) handleMatter() {
|
||||||
mchan := make(chan *MMMessage)
|
messages := make(chan *config.Message)
|
||||||
if b.Config.WebhookBindAddress != "" {
|
if b.GetString("WebhookBindAddress") != "" {
|
||||||
flog.Debugf("Choosing webhooks based receiving")
|
b.Log.Debugf("Choosing webhooks based receiving")
|
||||||
go b.handleMatterHook(mchan)
|
go b.handleMatterHook(messages)
|
||||||
} else {
|
} else {
|
||||||
if b.Config.Token != "" {
|
if b.GetString("Token") != "" {
|
||||||
flog.Debugf("Choosing token based receiving")
|
b.Log.Debugf("Choosing token based receiving")
|
||||||
} else {
|
} else {
|
||||||
flog.Debugf("Choosing login/password based receiving")
|
b.Log.Debugf("Choosing login/password based receiving")
|
||||||
}
|
}
|
||||||
go b.handleMatterClient(mchan)
|
go b.handleMatterClient(messages)
|
||||||
}
|
}
|
||||||
for message := range mchan {
|
var ok bool
|
||||||
rmsg := config.Message{Username: message.Username, Channel: message.Channel, Account: b.Account, UserID: message.UserID, ID: message.ID, Event: message.Event, Extra: message.Extra}
|
for message := range messages {
|
||||||
text, ok := b.replaceAction(message.Text)
|
message.Avatar = helper.GetAvatar(b.avatarMap, message.UserID, b.General)
|
||||||
|
message.Account = b.Account
|
||||||
|
message.Text, ok = b.replaceAction(message.Text)
|
||||||
if ok {
|
if ok {
|
||||||
rmsg.Event = config.EVENT_USER_ACTION
|
message.Event = config.EVENT_USER_ACTION
|
||||||
}
|
}
|
||||||
rmsg.Text = text
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", message.Username, b.Account)
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account)
|
b.Log.Debugf("<= Message is %#v", message)
|
||||||
flog.Debugf("Message is %#v", rmsg)
|
b.Remote <- *message
|
||||||
b.Remote <- rmsg
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) {
|
func (b *Bmattermost) handleMatterClient(messages chan *config.Message) {
|
||||||
for message := range b.mc.MessageChan {
|
for message := range b.mc.MessageChan {
|
||||||
flog.Debugf("%#v", message.Raw.Data)
|
b.Log.Debugf("%#v", message.Raw.Data)
|
||||||
if message.Type == "system_join_leave" ||
|
|
||||||
message.Type == "system_join_channel" ||
|
if b.skipMessage(message) {
|
||||||
message.Type == "system_leave_channel" {
|
b.Log.Debugf("Skipped message: %#v", message)
|
||||||
flog.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
|
||||||
b.Remote <- config.Message{Username: "system", Text: message.Text, Channel: message.Channel, Account: b.Account, Event: config.EVENT_JOIN_LEAVE}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (message.Raw.Event == "post_edited") && b.Config.EditDisable {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
m := &MMMessage{Extra: make(map[string][]interface{})}
|
// only download avatars if we have a place to upload them (configured mediaserver)
|
||||||
|
if b.General.MediaServerUpload != "" || b.General.MediaDownloadPath != "" {
|
||||||
|
b.handleDownloadAvatar(message.UserID, message.Channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Log.Debugf("== Receiving event %#v", message)
|
||||||
|
|
||||||
|
rmsg := &config.Message{Username: message.Username, UserID: message.UserID, Channel: message.Channel, Text: message.Text, ID: message.Post.Id, Extra: make(map[string][]interface{})}
|
||||||
|
|
||||||
|
// handle mattermost post properties (override username and attachments)
|
||||||
props := message.Post.Props
|
props := message.Post.Props
|
||||||
if props != nil {
|
if props != nil {
|
||||||
if _, ok := props["matterbridge"].(bool); ok {
|
|
||||||
flog.Debugf("sent by matterbridge, ignoring")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, ok := props["override_username"].(string); ok {
|
if _, ok := props["override_username"].(string); ok {
|
||||||
message.Username = props["override_username"].(string)
|
rmsg.Username = props["override_username"].(string)
|
||||||
}
|
}
|
||||||
if _, ok := props["attachments"].([]interface{}); ok {
|
if _, ok := props["attachments"].([]interface{}); ok {
|
||||||
m.Extra["attachments"] = props["attachments"].([]interface{})
|
rmsg.Extra["attachments"] = props["attachments"].([]interface{})
|
||||||
}
|
if rmsg.Text == "" {
|
||||||
}
|
for _, attachment := range rmsg.Extra["attachments"] {
|
||||||
// do not post our own messages back to irc
|
attach := attachment.(map[string]interface{})
|
||||||
// only listen to message from our team
|
if attach["text"].(string) != "" {
|
||||||
if (message.Raw.Event == "posted" || message.Raw.Event == "post_edited" || message.Raw.Event == "post_deleted") &&
|
rmsg.Text += attach["text"].(string)
|
||||||
b.mc.User.Username != message.Username && message.Raw.Data["team_id"].(string) == b.TeamId {
|
continue
|
||||||
// if the message has reactions don't repost it (for now, until we can correlate reaction with message)
|
}
|
||||||
if message.Post.HasReactions {
|
if attach["fallback"].(string) != "" {
|
||||||
continue
|
rmsg.Text += attach["fallback"].(string)
|
||||||
}
|
}
|
||||||
flog.Debugf("Receiving from matterclient %#v", message)
|
}
|
||||||
m.UserID = message.UserID
|
|
||||||
m.Username = message.Username
|
|
||||||
m.Channel = message.Channel
|
|
||||||
m.Text = message.Text
|
|
||||||
m.ID = message.Post.Id
|
|
||||||
if message.Raw.Event == "post_edited" && !b.Config.EditDisable {
|
|
||||||
m.Text = message.Text + b.Config.EditSuffix
|
|
||||||
}
|
|
||||||
if message.Raw.Event == "post_deleted" {
|
|
||||||
m.Event = config.EVENT_MSG_DELETE
|
|
||||||
}
|
|
||||||
if len(message.Post.FileIds) > 0 {
|
|
||||||
for _, link := range b.mc.GetFileLinks(message.Post.FileIds) {
|
|
||||||
m.Text = m.Text + "\n" + link
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mchan <- m
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a text for bridges that don't support native editing
|
||||||
|
if message.Raw.Event == "post_edited" && !b.GetBool("EditDisable") {
|
||||||
|
rmsg.Text = message.Text + b.GetString("EditSuffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
if message.Raw.Event == "post_deleted" {
|
||||||
|
rmsg.Event = config.EVENT_MSG_DELETE
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(message.Post.FileIds) > 0 {
|
||||||
|
for _, id := range message.Post.FileIds {
|
||||||
|
err := b.handleDownloadFile(rmsg, id)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("download failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use nickname instead of username if defined
|
||||||
|
if nick := b.mc.GetNickName(rmsg.UserID); nick != "" {
|
||||||
|
rmsg.Username = nick
|
||||||
|
}
|
||||||
|
|
||||||
|
messages <- rmsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmattermost) handleMatterHook(mchan chan *MMMessage) {
|
func (b *Bmattermost) handleMatterHook(messages chan *config.Message) {
|
||||||
for {
|
for {
|
||||||
message := b.mh.Receive()
|
message := b.mh.Receive()
|
||||||
flog.Debugf("Receiving from matterhook %#v", message)
|
b.Log.Debugf("Receiving from matterhook %#v", message)
|
||||||
m := &MMMessage{}
|
messages <- &config.Message{UserID: message.UserID, Username: message.UserName, Text: message.Text, Channel: message.ChannelName}
|
||||||
m.UserID = message.UserID
|
|
||||||
m.Username = message.UserName
|
|
||||||
m.Text = message.Text
|
|
||||||
m.Channel = message.ChannelName
|
|
||||||
mchan <- m
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bmattermost) apiLogin() error {
|
func (b *Bmattermost) apiLogin() error {
|
||||||
password := b.Config.Password
|
password := b.GetString("Password")
|
||||||
if b.Config.Token != "" {
|
if b.GetString("Token") != "" {
|
||||||
password = "MMAUTHTOKEN=" + b.Config.Token
|
password = "MMAUTHTOKEN=" + b.GetString("Token")
|
||||||
}
|
}
|
||||||
|
|
||||||
b.mc = matterclient.New(b.Config.Login, password,
|
b.mc = matterclient.New(b.GetString("Login"), password, b.GetString("Team"), b.GetString("Server"))
|
||||||
b.Config.Team, b.Config.Server)
|
if b.GetBool("debug") {
|
||||||
b.mc.SkipTLSVerify = b.Config.SkipTLSVerify
|
b.mc.SetLogLevel("debug")
|
||||||
b.mc.NoTLS = b.Config.NoTLS
|
}
|
||||||
flog.Infof("Connecting %s (team: %s) on %s", b.Config.Login, b.Config.Team, b.Config.Server)
|
b.mc.SkipTLSVerify = b.GetBool("SkipTLSVerify")
|
||||||
|
b.mc.NoTLS = b.GetBool("NoTLS")
|
||||||
|
b.Log.Infof("Connecting %s (team: %s) on %s", b.GetString("Login"), b.GetString("Team"), b.GetString("Server"))
|
||||||
err := b.mc.Login()
|
err := b.mc.Login()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
b.TeamId = b.mc.GetTeamId()
|
b.TeamID = b.mc.GetTeamId()
|
||||||
go b.mc.WsReceiver()
|
go b.mc.WsReceiver()
|
||||||
go b.mc.StatusLoop()
|
go b.mc.StatusLoop()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replaceAction replace the message with the correct action (/me) code
|
||||||
func (b *Bmattermost) replaceAction(text string) (string, bool) {
|
func (b *Bmattermost) replaceAction(text string) (string, bool) {
|
||||||
if strings.HasPrefix(text, "*") && strings.HasSuffix(text, "*") {
|
if strings.HasPrefix(text, "*") && strings.HasSuffix(text, "*") {
|
||||||
return strings.Replace(text, "*", "", -1), true
|
return strings.Replace(text, "*", "", -1), true
|
||||||
}
|
}
|
||||||
return text, false
|
return text, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bmattermost) cacheAvatar(msg *config.Message) (string, error) {
|
||||||
|
fi := msg.Extra["file"][0].(config.FileInfo)
|
||||||
|
/* if we have a sha we have successfully uploaded the file to the media server,
|
||||||
|
so we can now cache the sha */
|
||||||
|
if fi.SHA != "" {
|
||||||
|
b.Log.Debugf("Added %s to %s in avatarMap", fi.SHA, msg.UserID)
|
||||||
|
b.avatarMap[msg.UserID] = fi.SHA
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleDownloadAvatar downloads the avatar of userid from channel
|
||||||
|
// sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful.
|
||||||
|
// logs an error message if it fails
|
||||||
|
func (b *Bmattermost) handleDownloadAvatar(userid string, channel string) {
|
||||||
|
rmsg := config.Message{Username: "system", Text: "avatar", Channel: channel, Account: b.Account, UserID: userid, Event: config.EVENT_AVATAR_DOWNLOAD, Extra: make(map[string][]interface{})}
|
||||||
|
if _, ok := b.avatarMap[userid]; !ok {
|
||||||
|
data, resp := b.mc.Client.GetProfileImage(userid, "")
|
||||||
|
if resp.Error != nil {
|
||||||
|
b.Log.Errorf("ProfileImage download failed for %#v %s", userid, resp.Error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := helper.HandleDownloadSize(b.Log, &rmsg, userid+".png", int64(len(data)), b.General)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.HandleDownloadData(b.Log, &rmsg, userid+".png", rmsg.Text, "", &data, b.General)
|
||||||
|
b.Remote <- rmsg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleDownloadFile handles file download
|
||||||
|
func (b *Bmattermost) handleDownloadFile(rmsg *config.Message, id string) error {
|
||||||
|
url, _ := b.mc.Client.GetFileLink(id)
|
||||||
|
finfo, resp := b.mc.Client.GetFileInfo(id)
|
||||||
|
if resp.Error != nil {
|
||||||
|
return resp.Error
|
||||||
|
}
|
||||||
|
err := helper.HandleDownloadSize(b.Log, rmsg, finfo.Name, finfo.Size, b.General)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data, resp := b.mc.Client.DownloadFile(id, true)
|
||||||
|
if resp.Error != nil {
|
||||||
|
return resp.Error
|
||||||
|
}
|
||||||
|
helper.HandleDownloadData(b.Log, rmsg, finfo.Name, rmsg.Text, url, &data, b.General)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleUploadFile handles native upload of files
|
||||||
|
func (b *Bmattermost) handleUploadFile(msg *config.Message) (string, error) {
|
||||||
|
var err error
|
||||||
|
var res, id string
|
||||||
|
channelID := b.mc.GetChannelId(msg.Channel, "")
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
id, err = b.mc.UploadFile(*fi.Data, channelID, fi.Name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
msg.Text = fi.Comment
|
||||||
|
if b.GetBool("PrefixMessagesWithNick") {
|
||||||
|
msg.Text = msg.Username + msg.Text
|
||||||
|
}
|
||||||
|
res, err = b.mc.PostMessageWithFiles(channelID, msg.Text, []string{id})
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendWebhook uses the configured WebhookURL to send the message
|
||||||
|
func (b *Bmattermost) sendWebhook(msg config.Message) (string, error) {
|
||||||
|
// skip events
|
||||||
|
if msg.Event != "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.GetBool("PrefixMessagesWithNick") {
|
||||||
|
msg.Text = msg.Username + msg.Text
|
||||||
|
}
|
||||||
|
if msg.Extra != nil {
|
||||||
|
// this sends a message only if we received a config.EVENT_FILE_FAILURE_SIZE
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
iconURL := config.GetIconURL(&rmsg, b.GetString("iconurl"))
|
||||||
|
matterMessage := matterhook.OMessage{IconURL: iconURL, Channel: rmsg.Channel, UserName: rmsg.Username, Text: rmsg.Text, Props: make(map[string]interface{})}
|
||||||
|
matterMessage.Props["matterbridge_"+b.uuid] = true
|
||||||
|
b.mh.Send(matterMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// webhook doesn't support file uploads, so we add the url manually
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text += fi.URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iconURL := config.GetIconURL(&msg, b.GetString("iconurl"))
|
||||||
|
matterMessage := matterhook.OMessage{IconURL: iconURL, Channel: msg.Channel, UserName: msg.Username, Text: msg.Text, Props: make(map[string]interface{})}
|
||||||
|
if msg.Avatar != "" {
|
||||||
|
matterMessage.IconURL = msg.Avatar
|
||||||
|
}
|
||||||
|
matterMessage.Props["matterbridge_"+b.uuid] = true
|
||||||
|
err := b.mh.Send(matterMessage)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Info(err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipMessages returns true if this message should not be handled
|
||||||
|
func (b *Bmattermost) skipMessage(message *matterclient.Message) bool {
|
||||||
|
// Handle join/leave
|
||||||
|
if message.Type == "system_join_leave" ||
|
||||||
|
message.Type == "system_join_channel" ||
|
||||||
|
message.Type == "system_leave_channel" {
|
||||||
|
if b.GetBool("nosendjoinpart") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
b.Log.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
||||||
|
b.Remote <- config.Message{Username: "system", Text: message.Text, Channel: message.Channel, Account: b.Account, Event: config.EVENT_JOIN_LEAVE}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle edited messages
|
||||||
|
if (message.Raw.Event == "post_edited") && b.GetBool("EditDisable") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore messages sent from matterbridge
|
||||||
|
if message.Post.Props != nil {
|
||||||
|
if _, ok := message.Post.Props["matterbridge_"+b.uuid].(bool); ok {
|
||||||
|
b.Log.Debugf("sent by matterbridge, ignoring")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore messages sent from a user logged in as the bot
|
||||||
|
if b.mc.User.Username == message.Username {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the message has reactions don't repost it (for now, until we can correlate reaction with message)
|
||||||
|
if message.Post.HasReactions {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore messages from other teams than ours
|
||||||
|
if message.Raw.Data["team_id"].(string) != b.TeamID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// only handle posted, edited or deleted events
|
||||||
|
if !(message.Raw.Event == "posted" || message.Raw.Event == "post_edited" || message.Raw.Event == "post_deleted") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package brocketchat
|
package brocketchat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/42wim/matterbridge/hook/rockethook"
|
"github.com/42wim/matterbridge/hook/rockethook"
|
||||||
"github.com/42wim/matterbridge/matterhook"
|
"github.com/42wim/matterbridge/matterhook"
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MMhook struct {
|
type MMhook struct {
|
||||||
@@ -14,18 +15,11 @@ type MMhook struct {
|
|||||||
|
|
||||||
type Brocketchat struct {
|
type Brocketchat struct {
|
||||||
MMhook
|
MMhook
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "rocketchat"
|
return &Brocketchat{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Brocketchat {
|
|
||||||
return &Brocketchat{BridgeConfig: cfg}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Brocketchat) Command(cmd string) string {
|
func (b *Brocketchat) Command(cmd string) string {
|
||||||
@@ -33,11 +27,11 @@ func (b *Brocketchat) Command(cmd string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Brocketchat) Connect() error {
|
func (b *Brocketchat) Connect() error {
|
||||||
flog.Info("Connecting webhooks")
|
b.Log.Info("Connecting webhooks")
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
DisableServer: true})
|
DisableServer: true})
|
||||||
b.rh = rockethook.New(b.Config.WebhookURL, rockethook.Config{BindAddress: b.Config.WebhookBindAddress})
|
b.rh = rockethook.New(b.GetString("WebhookURL"), rockethook.Config{BindAddress: b.GetString("WebhookBindAddress")})
|
||||||
go b.handleRocketHook()
|
go b.handleRocketHook()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -56,15 +50,32 @@ func (b *Brocketchat) Send(msg config.Message) (string, error) {
|
|||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL}
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
iconURL := config.GetIconURL(&rmsg, b.GetString("iconurl"))
|
||||||
|
matterMessage := matterhook.OMessage{IconURL: iconURL, Channel: rmsg.Channel, UserName: rmsg.Username, Text: rmsg.Text}
|
||||||
|
b.mh.Send(matterMessage)
|
||||||
|
}
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text += fi.URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iconURL := config.GetIconURL(&msg, b.GetString("iconurl"))
|
||||||
|
matterMessage := matterhook.OMessage{IconURL: iconURL}
|
||||||
matterMessage.Channel = msg.Channel
|
matterMessage.Channel = msg.Channel
|
||||||
matterMessage.UserName = msg.Username
|
matterMessage.UserName = msg.Username
|
||||||
matterMessage.Type = ""
|
matterMessage.Type = ""
|
||||||
matterMessage.Text = msg.Text
|
matterMessage.Text = msg.Text
|
||||||
err := b.mh.Send(matterMessage)
|
err := b.mh.Send(matterMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Info(err)
|
b.Log.Info(err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
@@ -73,12 +84,12 @@ func (b *Brocketchat) Send(msg config.Message) (string, error) {
|
|||||||
func (b *Brocketchat) handleRocketHook() {
|
func (b *Brocketchat) handleRocketHook() {
|
||||||
for {
|
for {
|
||||||
message := b.rh.Receive()
|
message := b.rh.Receive()
|
||||||
flog.Debugf("Receiving from rockethook %#v", message)
|
b.Log.Debugf("Receiving from rockethook %#v", message)
|
||||||
// do not loop
|
// do not loop
|
||||||
if message.UserName == b.Config.Nick {
|
if message.UserName == b.GetString("Nick") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", message.UserName, b.Account)
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", message.UserName, b.Account)
|
||||||
b.Remote <- config.Message{Text: message.Text, Username: message.UserName, Channel: message.ChannelName, Account: b.Account, UserID: message.UserID}
|
b.Remote <- config.Message{Text: message.Text, Username: message.UserName, Channel: message.ChannelName, Account: b.Account, UserID: message.UserID}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,46 +4,42 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
"github.com/42wim/matterbridge/matterhook"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/matterbridge/slack"
|
|
||||||
"html"
|
"html"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
"github.com/42wim/matterbridge/matterhook"
|
||||||
|
"github.com/hashicorp/golang-lru"
|
||||||
|
"github.com/nlopes/slack"
|
||||||
|
"github.com/rs/xid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MMMessage struct {
|
|
||||||
Text string
|
|
||||||
Channel string
|
|
||||||
Username string
|
|
||||||
UserID string
|
|
||||||
Raw *slack.MessageEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
type Bslack struct {
|
type Bslack struct {
|
||||||
mh *matterhook.Client
|
mh *matterhook.Client
|
||||||
sc *slack.Client
|
sc *slack.Client
|
||||||
rtm *slack.RTM
|
rtm *slack.RTM
|
||||||
Plus bool
|
Users []slack.User
|
||||||
Users []slack.User
|
Usergroups []slack.UserGroup
|
||||||
si *slack.Info
|
si *slack.Info
|
||||||
channels []slack.Channel
|
channels []slack.Channel
|
||||||
*config.BridgeConfig
|
cache *lru.Cache
|
||||||
|
UseChannelID bool
|
||||||
|
uuid string
|
||||||
|
*bridge.Config
|
||||||
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
const messageDeleted = "message_deleted"
|
||||||
var protocol = "slack"
|
|
||||||
|
|
||||||
func init() {
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
b := &Bslack{Config: cfg, uuid: xid.New().String()}
|
||||||
}
|
b.cache, _ = lru.New(5000)
|
||||||
|
return b
|
||||||
func New(cfg *config.BridgeConfig) *Bslack {
|
|
||||||
return &Bslack{BridgeConfig: cfg}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) Command(cmd string) string {
|
func (b *Bslack) Command(cmd string) string {
|
||||||
@@ -51,71 +47,90 @@ func (b *Bslack) Command(cmd string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) Connect() error {
|
func (b *Bslack) Connect() error {
|
||||||
if b.Config.WebhookBindAddress != "" {
|
b.RLock()
|
||||||
if b.Config.WebhookURL != "" {
|
defer b.RUnlock()
|
||||||
flog.Info("Connecting using webhookurl (sending) and webhookbindaddress (receiving)")
|
if b.GetString("WebhookBindAddress") != "" {
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
if b.GetString("WebhookURL") != "" {
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
b.Log.Info("Connecting using webhookurl (sending) and webhookbindaddress (receiving)")
|
||||||
BindAddress: b.Config.WebhookBindAddress})
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
} else if b.Config.Token != "" {
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
flog.Info("Connecting using token (sending)")
|
BindAddress: b.GetString("WebhookBindAddress")})
|
||||||
b.sc = slack.New(b.Config.Token)
|
} else if b.GetString("Token") != "" {
|
||||||
|
b.Log.Info("Connecting using token (sending)")
|
||||||
|
b.sc = slack.New(b.GetString("Token"))
|
||||||
b.rtm = b.sc.NewRTM()
|
b.rtm = b.sc.NewRTM()
|
||||||
go b.rtm.ManageConnection()
|
go b.rtm.ManageConnection()
|
||||||
flog.Info("Connecting using webhookbindaddress (receiving)")
|
b.Log.Info("Connecting using webhookbindaddress (receiving)")
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
BindAddress: b.Config.WebhookBindAddress})
|
BindAddress: b.GetString("WebhookBindAddress")})
|
||||||
} else {
|
} else {
|
||||||
flog.Info("Connecting using webhookbindaddress (receiving)")
|
b.Log.Info("Connecting using webhookbindaddress (receiving)")
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
BindAddress: b.Config.WebhookBindAddress})
|
BindAddress: b.GetString("WebhookBindAddress")})
|
||||||
}
|
}
|
||||||
go b.handleSlack()
|
go b.handleSlack()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if b.Config.WebhookURL != "" {
|
if b.GetString("WebhookURL") != "" {
|
||||||
flog.Info("Connecting using webhookurl (sending)")
|
b.Log.Info("Connecting using webhookurl (sending)")
|
||||||
b.mh = matterhook.New(b.Config.WebhookURL,
|
b.mh = matterhook.New(b.GetString("WebhookURL"),
|
||||||
matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify,
|
matterhook.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"),
|
||||||
DisableServer: true})
|
DisableServer: true})
|
||||||
if b.Config.Token != "" {
|
if b.GetString("Token") != "" {
|
||||||
flog.Info("Connecting using token (receiving)")
|
b.Log.Info("Connecting using token (receiving)")
|
||||||
b.sc = slack.New(b.Config.Token)
|
b.sc = slack.New(b.GetString("Token"))
|
||||||
b.rtm = b.sc.NewRTM()
|
b.rtm = b.sc.NewRTM()
|
||||||
go b.rtm.ManageConnection()
|
go b.rtm.ManageConnection()
|
||||||
go b.handleSlack()
|
go b.handleSlack()
|
||||||
}
|
}
|
||||||
} else if b.Config.Token != "" {
|
} else if b.GetString("Token") != "" {
|
||||||
flog.Info("Connecting using token (sending and receiving)")
|
b.Log.Info("Connecting using token (sending and receiving)")
|
||||||
b.sc = slack.New(b.Config.Token)
|
b.sc = slack.New(b.GetString("Token"))
|
||||||
b.rtm = b.sc.NewRTM()
|
b.rtm = b.sc.NewRTM()
|
||||||
go b.rtm.ManageConnection()
|
go b.rtm.ManageConnection()
|
||||||
go b.handleSlack()
|
go b.handleSlack()
|
||||||
}
|
}
|
||||||
if b.Config.WebhookBindAddress == "" && b.Config.WebhookURL == "" && b.Config.Token == "" {
|
if b.GetString("WebhookBindAddress") == "" && b.GetString("WebhookURL") == "" && b.GetString("Token") == "" {
|
||||||
return errors.New("No connection method found. See that you have WebhookBindAddress, WebhookURL or Token configured.")
|
return errors.New("no connection method found. See that you have WebhookBindAddress, WebhookURL or Token configured")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) Disconnect() error {
|
func (b *Bslack) Disconnect() error {
|
||||||
return nil
|
return b.rtm.Disconnect()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Bslack) JoinChannel(channel config.ChannelInfo) error {
|
||||||
|
// use ID:channelid and resolve it to the actual name
|
||||||
|
idcheck := strings.Split(channel.Name, "ID:")
|
||||||
|
if len(idcheck) > 1 {
|
||||||
|
b.UseChannelID = true
|
||||||
|
ch, err := b.sc.GetChannelInfo(idcheck[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
channel.Name = ch.Name
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// we can only join channels using the API
|
// we can only join channels using the API
|
||||||
if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" {
|
if b.sc != nil {
|
||||||
if strings.HasPrefix(b.Config.Token, "xoxb") {
|
if strings.HasPrefix(b.GetString("Token"), "xoxb") {
|
||||||
// TODO check if bot has already joined channel
|
// TODO check if bot has already joined channel
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_, err := b.sc.JoinChannel(channel.Name)
|
_, err := b.sc.JoinChannel(channel.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != "name_taken" {
|
switch err.Error() {
|
||||||
return err
|
case "name_taken", "restricted_action":
|
||||||
|
case "default":
|
||||||
|
{
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,48 +138,21 @@ func (b *Bslack) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) Send(msg config.Message) (string, error) {
|
func (b *Bslack) Send(msg config.Message) (string, error) {
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
|
// Make a action /me of the message
|
||||||
if msg.Event == config.EVENT_USER_ACTION {
|
if msg.Event == config.EVENT_USER_ACTION {
|
||||||
msg.Text = "_" + msg.Text + "_"
|
msg.Text = "_" + msg.Text + "_"
|
||||||
}
|
}
|
||||||
nick := msg.Username
|
|
||||||
message := msg.Text
|
|
||||||
channel := msg.Channel
|
|
||||||
if b.Config.PrefixMessagesWithNick {
|
|
||||||
message = nick + " " + message
|
|
||||||
}
|
|
||||||
if b.Config.WebhookURL != "" {
|
|
||||||
matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL}
|
|
||||||
matterMessage.Channel = channel
|
|
||||||
matterMessage.UserName = nick
|
|
||||||
matterMessage.Type = ""
|
|
||||||
matterMessage.Text = message
|
|
||||||
err := b.mh.Send(matterMessage)
|
|
||||||
if err != nil {
|
|
||||||
flog.Info(err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
schannel, err := b.getChannelByName(channel)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
np := slack.NewPostMessageParameters()
|
|
||||||
if b.Config.PrefixMessagesWithNick {
|
|
||||||
np.AsUser = true
|
|
||||||
}
|
|
||||||
np.Username = nick
|
|
||||||
np.IconURL = config.GetIconURL(&msg, &b.Config)
|
|
||||||
if msg.Avatar != "" {
|
|
||||||
np.IconURL = msg.Avatar
|
|
||||||
}
|
|
||||||
np.Attachments = append(np.Attachments, slack.Attachment{CallbackID: "matterbridge"})
|
|
||||||
np.Attachments = append(np.Attachments, b.createAttach(msg.Extra)...)
|
|
||||||
|
|
||||||
// replace mentions
|
// Use webhook to send the message
|
||||||
np.LinkNames = 1
|
if b.GetString("WebhookURL") != "" {
|
||||||
|
return b.sendWebhook(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
channelID := b.getChannelID(msg.Channel)
|
||||||
|
|
||||||
|
// Delete message
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
// some protocols echo deletes, but with empty ID
|
// some protocols echo deletes, but with empty ID
|
||||||
if msg.ID == "" {
|
if msg.ID == "" {
|
||||||
@@ -172,47 +160,78 @@ func (b *Bslack) Send(msg config.Message) (string, error) {
|
|||||||
}
|
}
|
||||||
// we get a "slack <ID>", split it
|
// we get a "slack <ID>", split it
|
||||||
ts := strings.Fields(msg.ID)
|
ts := strings.Fields(msg.ID)
|
||||||
b.sc.DeleteMessage(schannel.ID, ts[1])
|
_, _, err := b.sc.DeleteMessage(channelID, ts[1])
|
||||||
return "", nil
|
if err != nil {
|
||||||
}
|
return msg.ID, err
|
||||||
// if we have no ID it means we're creating a new message, not updating an existing one
|
}
|
||||||
if msg.ID != "" {
|
return msg.ID, nil
|
||||||
ts := strings.Fields(msg.ID)
|
|
||||||
b.sc.UpdateMessage(schannel.ID, ts[1], message)
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.Extra != nil {
|
// Prepend nick if configured
|
||||||
// check if we have files to upload (from slack, telegram or mattermost)
|
if b.GetBool("PrefixMessagesWithNick") {
|
||||||
if len(msg.Extra["file"]) > 0 {
|
msg.Text = msg.Username + msg.Text
|
||||||
var err error
|
}
|
||||||
for _, f := range msg.Extra["file"] {
|
|
||||||
fi := f.(config.FileInfo)
|
// Edit message if we have an ID
|
||||||
_, err = b.sc.UploadFile(slack.FileUploadParameters{
|
if msg.ID != "" {
|
||||||
Reader: bytes.NewReader(*fi.Data),
|
ts := strings.Fields(msg.ID)
|
||||||
Filename: fi.Name,
|
_, _, _, err := b.sc.UpdateMessage(channelID, ts[1], msg.Text)
|
||||||
Channels: []string{schannel.ID},
|
if err != nil {
|
||||||
InitialComment: fi.Comment,
|
return msg.ID, err
|
||||||
})
|
}
|
||||||
if err != nil {
|
return msg.ID, nil
|
||||||
flog.Errorf("uploadfile %#v", err)
|
}
|
||||||
}
|
|
||||||
}
|
// create slack new post parameters
|
||||||
|
np := slack.NewPostMessageParameters()
|
||||||
|
if b.GetBool("PrefixMessagesWithNick") {
|
||||||
|
np.AsUser = true
|
||||||
|
}
|
||||||
|
np.Username = msg.Username
|
||||||
|
np.LinkNames = 1 // replace mentions
|
||||||
|
np.IconURL = config.GetIconURL(&msg, b.GetString("iconurl"))
|
||||||
|
if msg.Avatar != "" {
|
||||||
|
np.IconURL = msg.Avatar
|
||||||
|
}
|
||||||
|
// add a callback ID so we can see we created it
|
||||||
|
np.Attachments = append(np.Attachments, slack.Attachment{CallbackID: "matterbridge_" + b.uuid})
|
||||||
|
// add file attachments
|
||||||
|
np.Attachments = append(np.Attachments, b.createAttach(msg.Extra)...)
|
||||||
|
// add slack attachments (from another slack bridge)
|
||||||
|
if len(msg.Extra["slack_attachment"]) > 0 {
|
||||||
|
for _, attach := range msg.Extra["slack_attachment"] {
|
||||||
|
np.Attachments = append(np.Attachments, attach.([]slack.Attachment)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, id, err := b.sc.PostMessage(schannel.ID, message, np)
|
// Upload a file if it exists
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.sc.PostMessage(channelID, rmsg.Username+rmsg.Text, np)
|
||||||
|
}
|
||||||
|
// check if we have files to upload (from slack, telegram or mattermost)
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
b.handleUploadFile(&msg, channelID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post normal message
|
||||||
|
_, id, err := b.sc.PostMessage(channelID, msg.Text, np)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return "slack " + id, nil
|
return "slack " + id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) getAvatar(user string) string {
|
func (b *Bslack) Reload(cfg *bridge.Config) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bslack) getAvatar(userid string) string {
|
||||||
var avatar string
|
var avatar string
|
||||||
if b.Users != nil {
|
if b.Users != nil {
|
||||||
for _, u := range b.Users {
|
for _, u := range b.Users {
|
||||||
if user == u.Name {
|
if userid == u.ID {
|
||||||
return u.Profile.Image48
|
return u.Profile.Image48
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,6 +239,7 @@ func (b *Bslack) getAvatar(user string) string {
|
|||||||
return avatar
|
return avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func (b *Bslack) getChannelByName(name string) (*slack.Channel, error) {
|
func (b *Bslack) getChannelByName(name string) (*slack.Channel, error) {
|
||||||
if b.channels == nil {
|
if b.channels == nil {
|
||||||
return nil, fmt.Errorf("%s: channel %s not found (no channels found)", b.Account, name)
|
return nil, fmt.Errorf("%s: channel %s not found (no channels found)", b.Account, name)
|
||||||
@@ -231,6 +251,7 @@ func (b *Bslack) getChannelByName(name string) (*slack.Channel, error) {
|
|||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%s: channel %s not found", b.Account, name)
|
return nil, fmt.Errorf("%s: channel %s not found", b.Account, name)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (b *Bslack) getChannelByID(ID string) (*slack.Channel, error) {
|
func (b *Bslack) getChannelByID(ID string) (*slack.Channel, error) {
|
||||||
if b.channels == nil {
|
if b.channels == nil {
|
||||||
@@ -245,175 +266,82 @@ func (b *Bslack) getChannelByID(ID string) (*slack.Channel, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) handleSlack() {
|
func (b *Bslack) handleSlack() {
|
||||||
mchan := make(chan *MMMessage)
|
messages := make(chan *config.Message)
|
||||||
if b.Config.WebhookBindAddress != "" {
|
if b.GetString("WebhookBindAddress") != "" {
|
||||||
flog.Debugf("Choosing webhooks based receiving")
|
b.Log.Debugf("Choosing webhooks based receiving")
|
||||||
go b.handleMatterHook(mchan)
|
go b.handleMatterHook(messages)
|
||||||
} else {
|
} else {
|
||||||
flog.Debugf("Choosing token based receiving")
|
b.Log.Debugf("Choosing token based receiving")
|
||||||
go b.handleSlackClient(mchan)
|
go b.handleSlackClient(messages)
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
flog.Debug("Start listening for Slack messages")
|
b.Log.Debug("Start listening for Slack messages")
|
||||||
for message := range mchan {
|
for message := range messages {
|
||||||
// do not send messages from ourself
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", message.Username, b.Account)
|
||||||
if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" && message.Username == b.si.User.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (message.Text == "" || message.Username == "") && message.Raw.SubType != "message_deleted" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
text := message.Text
|
|
||||||
text = b.replaceURL(text)
|
|
||||||
text = html.UnescapeString(text)
|
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account)
|
|
||||||
msg := config.Message{Text: text, Username: message.Username, Channel: message.Channel, Account: b.Account, Avatar: b.getAvatar(message.Username), UserID: message.UserID, ID: "slack " + message.Raw.Timestamp, Extra: make(map[string][]interface{})}
|
|
||||||
if message.Raw.SubType == "me_message" {
|
|
||||||
msg.Event = config.EVENT_USER_ACTION
|
|
||||||
}
|
|
||||||
if message.Raw.SubType == "channel_leave" || message.Raw.SubType == "channel_join" {
|
|
||||||
msg.Username = "system"
|
|
||||||
msg.Event = config.EVENT_JOIN_LEAVE
|
|
||||||
}
|
|
||||||
// edited messages have a submessage, use this timestamp
|
|
||||||
if message.Raw.SubMessage != nil {
|
|
||||||
msg.ID = "slack " + message.Raw.SubMessage.Timestamp
|
|
||||||
}
|
|
||||||
if message.Raw.SubType == "message_deleted" {
|
|
||||||
msg.Text = config.EVENT_MSG_DELETE
|
|
||||||
msg.Event = config.EVENT_MSG_DELETE
|
|
||||||
msg.ID = "slack " + message.Raw.DeletedTimestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra
|
// cleanup the message
|
||||||
if message.Raw.File != nil {
|
message.Text = b.replaceMention(message.Text)
|
||||||
// limit to 1MB for now
|
message.Text = b.replaceVariable(message.Text)
|
||||||
if message.Raw.File.Size <= b.General.MediaDownloadSize {
|
message.Text = b.replaceChannel(message.Text)
|
||||||
comment := ""
|
message.Text = b.replaceURL(message.Text)
|
||||||
data, err := b.downloadFile(message.Raw.File.URLPrivateDownload)
|
message.Text = html.UnescapeString(message.Text)
|
||||||
if err != nil {
|
|
||||||
flog.Errorf("download %s failed %#v", message.Raw.File.URLPrivateDownload, err)
|
// Add the avatar
|
||||||
} else {
|
message.Avatar = b.getAvatar(message.UserID)
|
||||||
results := regexp.MustCompile(`.*?commented: (.*)`).FindAllStringSubmatch(msg.Text, -1)
|
|
||||||
if len(results) > 0 {
|
b.Log.Debugf("<= Message is %#v", message)
|
||||||
comment = results[0][1]
|
b.Remote <- *message
|
||||||
}
|
|
||||||
msg.Extra["file"] = append(msg.Extra["file"], config.FileInfo{Name: message.Raw.File.Name, Data: data, Comment: comment})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flog.Debugf("Message is %#v", msg)
|
|
||||||
b.Remote <- msg
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) handleSlackClient(mchan chan *MMMessage) {
|
func (b *Bslack) handleSlackClient(messages chan *config.Message) {
|
||||||
for msg := range b.rtm.IncomingEvents {
|
for msg := range b.rtm.IncomingEvents {
|
||||||
|
if msg.Type != "user_typing" && msg.Type != "latency_report" {
|
||||||
|
b.Log.Debugf("== Receiving event %#v", msg.Data)
|
||||||
|
}
|
||||||
switch ev := msg.Data.(type) {
|
switch ev := msg.Data.(type) {
|
||||||
case *slack.MessageEvent:
|
case *slack.MessageEvent:
|
||||||
flog.Debugf("Receiving from slackclient %#v", ev)
|
if b.skipMessageEvent(ev) {
|
||||||
if len(ev.Attachments) > 0 {
|
b.Log.Debugf("Skipped message: %#v", ev)
|
||||||
// skip messages we made ourselves
|
|
||||||
if ev.Attachments[0].CallbackID == "matterbridge" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !b.Config.EditDisable && ev.SubMessage != nil && ev.SubMessage.ThreadTimestamp != ev.SubMessage.Timestamp {
|
|
||||||
flog.Debugf("SubMessage %#v", ev.SubMessage)
|
|
||||||
ev.User = ev.SubMessage.User
|
|
||||||
ev.Text = ev.SubMessage.Text + b.Config.EditSuffix
|
|
||||||
|
|
||||||
// it seems ev.SubMessage.Edited == nil when slack unfurls
|
|
||||||
// do not forward these messages #266
|
|
||||||
if ev.SubMessage.Edited == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// use our own func because rtm.GetChannelInfo doesn't work for private channels
|
|
||||||
channel, err := b.getChannelByID(ev.Channel)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
m := &MMMessage{}
|
rmsg, err := b.handleMessageEvent(ev)
|
||||||
if ev.BotID == "" && ev.SubType != "message_deleted" {
|
if err != nil {
|
||||||
user, err := b.rtm.GetUserInfo(ev.User)
|
b.Log.Errorf("%#v", err)
|
||||||
if err != nil {
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
m.UserID = user.ID
|
|
||||||
m.Username = user.Name
|
|
||||||
if user.Profile.DisplayName != "" {
|
|
||||||
m.Username = user.Profile.DisplayName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m.Channel = channel.Name
|
messages <- rmsg
|
||||||
m.Text = ev.Text
|
|
||||||
if m.Text == "" {
|
|
||||||
for _, attach := range ev.Attachments {
|
|
||||||
if attach.Text != "" {
|
|
||||||
m.Text = attach.Text
|
|
||||||
} else {
|
|
||||||
m.Text = attach.Fallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Raw = ev
|
|
||||||
m.Text = b.replaceMention(m.Text)
|
|
||||||
m.Text = b.replaceVariable(m.Text)
|
|
||||||
m.Text = b.replaceChannel(m.Text)
|
|
||||||
// when using webhookURL we can't check if it's our webhook or not for now
|
|
||||||
if ev.BotID != "" && b.Config.WebhookURL == "" {
|
|
||||||
bot, err := b.rtm.GetBotInfo(ev.BotID)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if bot.Name != "" {
|
|
||||||
m.Username = bot.Name
|
|
||||||
if ev.Username != "" {
|
|
||||||
m.Username = ev.Username
|
|
||||||
}
|
|
||||||
m.UserID = bot.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mchan <- m
|
|
||||||
case *slack.OutgoingErrorEvent:
|
case *slack.OutgoingErrorEvent:
|
||||||
flog.Debugf("%#v", ev.Error())
|
b.Log.Debugf("%#v", ev.Error())
|
||||||
case *slack.ChannelJoinedEvent:
|
case *slack.ChannelJoinedEvent:
|
||||||
b.Users, _ = b.sc.GetUsers()
|
b.Users, _ = b.sc.GetUsers()
|
||||||
|
b.Usergroups, _ = b.sc.GetUserGroups()
|
||||||
case *slack.ConnectedEvent:
|
case *slack.ConnectedEvent:
|
||||||
b.channels = ev.Info.Channels
|
var err error
|
||||||
|
b.channels, _, err = b.sc.GetConversations(&slack.GetConversationsParameters{Limit: 1000, Types: []string{"public_channel,private_channel,mpim,im"}})
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("Channel list failed: %#v", err)
|
||||||
|
}
|
||||||
b.si = ev.Info
|
b.si = ev.Info
|
||||||
b.Users, _ = b.sc.GetUsers()
|
b.Users, _ = b.sc.GetUsers()
|
||||||
// add private channels
|
b.Usergroups, _ = b.sc.GetUserGroups()
|
||||||
groups, _ := b.sc.GetGroups(true)
|
|
||||||
for _, g := range groups {
|
|
||||||
channel := new(slack.Channel)
|
|
||||||
channel.ID = g.ID
|
|
||||||
channel.Name = g.Name
|
|
||||||
b.channels = append(b.channels, *channel)
|
|
||||||
}
|
|
||||||
case *slack.InvalidAuthEvent:
|
case *slack.InvalidAuthEvent:
|
||||||
flog.Fatalf("Invalid Token %#v", ev)
|
b.Log.Fatalf("Invalid Token %#v", ev)
|
||||||
|
case *slack.ConnectionErrorEvent:
|
||||||
|
b.Log.Errorf("Connection failed %#v %#v", ev.Error(), ev.ErrorObj)
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) handleMatterHook(mchan chan *MMMessage) {
|
func (b *Bslack) handleMatterHook(messages chan *config.Message) {
|
||||||
for {
|
for {
|
||||||
message := b.mh.Receive()
|
message := b.mh.Receive()
|
||||||
flog.Debugf("receiving from matterhook (slack) %#v", message)
|
b.Log.Debugf("receiving from matterhook (slack) %#v", message)
|
||||||
m := &MMMessage{}
|
if message.UserName == "slackbot" {
|
||||||
m.Username = message.UserName
|
|
||||||
m.Text = message.Text
|
|
||||||
m.Text = b.replaceMention(m.Text)
|
|
||||||
m.Text = b.replaceVariable(m.Text)
|
|
||||||
m.Text = b.replaceChannel(m.Text)
|
|
||||||
m.Channel = message.ChannelName
|
|
||||||
if m.Username == "slackbot" {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mchan <- m
|
messages <- &config.Message{Username: message.UserName, Text: message.Text, Channel: message.ChannelName}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,9 +357,20 @@ func (b *Bslack) userName(id string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func (b *Bslack) userGroupName(id string) string {
|
||||||
|
for _, u := range b.Usergroups {
|
||||||
|
if u.ID == id {
|
||||||
|
return u.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// @see https://api.slack.com/docs/message-formatting#linking_to_channels_and_users
|
// @see https://api.slack.com/docs/message-formatting#linking_to_channels_and_users
|
||||||
func (b *Bslack) replaceMention(text string) string {
|
func (b *Bslack) replaceMention(text string) string {
|
||||||
results := regexp.MustCompile(`<@([a-zA-z0-9]+)>`).FindAllStringSubmatch(text, -1)
|
results := regexp.MustCompile(`<@([a-zA-Z0-9]+)>`).FindAllStringSubmatch(text, -1)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
text = strings.Replace(text, "<@"+r[1]+">", "@"+b.userName(r[1]), -1)
|
text = strings.Replace(text, "<@"+r[1]+">", "@"+b.userName(r[1]), -1)
|
||||||
}
|
}
|
||||||
@@ -449,9 +388,13 @@ func (b *Bslack) replaceChannel(text string) string {
|
|||||||
|
|
||||||
// @see https://api.slack.com/docs/message-formatting#variables
|
// @see https://api.slack.com/docs/message-formatting#variables
|
||||||
func (b *Bslack) replaceVariable(text string) string {
|
func (b *Bslack) replaceVariable(text string) string {
|
||||||
results := regexp.MustCompile(`<!([a-zA-Z0-9]+)(\|.+?)?>`).FindAllStringSubmatch(text, -1)
|
results := regexp.MustCompile(`<!((?:subteam\^)?[a-zA-Z0-9]+)(?:\|@?(.+?))?>`).FindAllStringSubmatch(text, -1)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
text = strings.Replace(text, r[0], "@"+r[1], -1)
|
if r[2] != "" {
|
||||||
|
text = strings.Replace(text, r[0], "@"+r[2], -1)
|
||||||
|
} else {
|
||||||
|
text = strings.Replace(text, r[0], "@"+r[1], -1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
@@ -460,7 +403,11 @@ func (b *Bslack) replaceVariable(text string) string {
|
|||||||
func (b *Bslack) replaceURL(text string) string {
|
func (b *Bslack) replaceURL(text string) string {
|
||||||
results := regexp.MustCompile(`<(.*?)(\|.*?)?>`).FindAllStringSubmatch(text, -1)
|
results := regexp.MustCompile(`<(.*?)(\|.*?)?>`).FindAllStringSubmatch(text, -1)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
text = strings.Replace(text, r[0], r[1], -1)
|
if len(strings.TrimSpace(r[2])) == 1 { // A display text separator was found, but the text was blank
|
||||||
|
text = strings.Replace(text, r[0], "", -1)
|
||||||
|
} else {
|
||||||
|
text = strings.Replace(text, r[0], r[1], -1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
@@ -488,23 +435,310 @@ func (b *Bslack) createAttach(extra map[string][]interface{}) []slack.Attachment
|
|||||||
return attachs
|
return attachs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bslack) downloadFile(url string) (*[]byte, error) {
|
// handleDownloadFile handles file download
|
||||||
var buf bytes.Buffer
|
func (b *Bslack) handleDownloadFile(rmsg *config.Message, file *slack.File) error {
|
||||||
client := &http.Client{
|
// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra
|
||||||
Timeout: time.Second * 5,
|
// limit to 1MB for now
|
||||||
|
comment := ""
|
||||||
|
results := regexp.MustCompile(`.*?commented: (.*)`).FindAllStringSubmatch(rmsg.Text, -1)
|
||||||
|
if len(results) > 0 {
|
||||||
|
comment = results[0][1]
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
err := helper.HandleDownloadSize(b.Log, rmsg, file.Name, int64(file.Size), b.General)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
req.Header.Add("Authorization", "Bearer "+b.Config.Token)
|
// actually download the file
|
||||||
resp, err := client.Do(req)
|
data, err := helper.DownloadFileAuth(file.URLPrivateDownload, "Bearer "+b.GetString("Token"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Body.Close()
|
return fmt.Errorf("download %s failed %#v", file.URLPrivateDownload, err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
io.Copy(&buf, resp.Body)
|
// add the downloaded data to the message
|
||||||
data := buf.Bytes()
|
helper.HandleDownloadData(b.Log, rmsg, file.Name, comment, file.URLPrivateDownload, data, b.General)
|
||||||
resp.Body.Close()
|
return nil
|
||||||
return &data, nil
|
}
|
||||||
|
|
||||||
|
// handleUploadFile handles native upload of files
|
||||||
|
func (b *Bslack) handleUploadFile(msg *config.Message, channelID string) (string, error) {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if msg.Text == fi.Comment {
|
||||||
|
msg.Text = ""
|
||||||
|
}
|
||||||
|
/* because the result of the UploadFile is slower than the MessageEvent from slack
|
||||||
|
we can't match on the file ID yet, so we have to match on the filename too
|
||||||
|
*/
|
||||||
|
b.Log.Debugf("Adding file %s to cache %s", fi.Name, time.Now().String())
|
||||||
|
b.cache.Add("filename"+fi.Name, time.Now())
|
||||||
|
res, err := b.sc.UploadFile(slack.FileUploadParameters{
|
||||||
|
Reader: bytes.NewReader(*fi.Data),
|
||||||
|
Filename: fi.Name,
|
||||||
|
Channels: []string{channelID},
|
||||||
|
InitialComment: fi.Comment,
|
||||||
|
})
|
||||||
|
if res.ID != "" {
|
||||||
|
b.Log.Debugf("Adding fileid %s to cache %s", res.ID, time.Now().String())
|
||||||
|
b.cache.Add("file"+res.ID, time.Now())
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("uploadfile %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleMessageEvent handles the message events
|
||||||
|
func (b *Bslack) handleMessageEvent(ev *slack.MessageEvent) (*config.Message, error) {
|
||||||
|
// update the userlist on a channel_join
|
||||||
|
if ev.SubType == "channel_join" {
|
||||||
|
b.Users, _ = b.sc.GetUsers()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit message
|
||||||
|
if !b.GetBool("EditDisable") && ev.SubMessage != nil && ev.SubMessage.ThreadTimestamp != ev.SubMessage.Timestamp {
|
||||||
|
b.Log.Debugf("SubMessage %#v", ev.SubMessage)
|
||||||
|
ev.User = ev.SubMessage.User
|
||||||
|
ev.Text = ev.SubMessage.Text + b.GetString("EditSuffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
// use our own func because rtm.GetChannelInfo doesn't work for private channels
|
||||||
|
channel, err := b.getChannelByID(ev.Channel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rmsg := config.Message{Text: ev.Text, Channel: channel.Name, Account: b.Account, ID: "slack " + ev.Timestamp, Extra: make(map[string][]interface{})}
|
||||||
|
|
||||||
|
if b.UseChannelID {
|
||||||
|
rmsg.Channel = "ID:" + channel.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the user id and name
|
||||||
|
if ev.User != "" && ev.SubType != messageDeleted && ev.SubType != "file_comment" {
|
||||||
|
user, err := b.rtm.GetUserInfo(ev.User)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rmsg.UserID = user.ID
|
||||||
|
rmsg.Username = user.Name
|
||||||
|
if user.Profile.DisplayName != "" {
|
||||||
|
rmsg.Username = user.Profile.DisplayName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we have some text in the attachments
|
||||||
|
if rmsg.Text == "" {
|
||||||
|
for _, attach := range ev.Attachments {
|
||||||
|
if attach.Text != "" {
|
||||||
|
if attach.Title != "" {
|
||||||
|
rmsg.Text = attach.Title + "\n"
|
||||||
|
}
|
||||||
|
rmsg.Text += attach.Text
|
||||||
|
} else {
|
||||||
|
rmsg.Text = attach.Fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when using webhookURL we can't check if it's our webhook or not for now
|
||||||
|
if rmsg.Username == "" && ev.BotID != "" && b.GetString("WebhookURL") == "" {
|
||||||
|
bot, err := b.rtm.GetBotInfo(ev.BotID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if bot.Name != "" {
|
||||||
|
rmsg.Username = bot.Name
|
||||||
|
if ev.Username != "" {
|
||||||
|
rmsg.Username = ev.Username
|
||||||
|
}
|
||||||
|
rmsg.UserID = bot.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixes issues with matterircd users
|
||||||
|
if bot.Name == "Slack API Tester" {
|
||||||
|
user, err := b.rtm.GetUserInfo(ev.User)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rmsg.UserID = user.ID
|
||||||
|
rmsg.Username = user.Name
|
||||||
|
if user.Profile.DisplayName != "" {
|
||||||
|
rmsg.Username = user.Profile.DisplayName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// file comments are set by the system (because there is no username given)
|
||||||
|
if ev.SubType == "file_comment" {
|
||||||
|
rmsg.Username = "system"
|
||||||
|
}
|
||||||
|
|
||||||
|
// do we have a /me action
|
||||||
|
if ev.SubType == "me_message" {
|
||||||
|
rmsg.Event = config.EVENT_USER_ACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle join/leave
|
||||||
|
if ev.SubType == "channel_leave" || ev.SubType == "channel_join" {
|
||||||
|
rmsg.Username = "system"
|
||||||
|
rmsg.Event = config.EVENT_JOIN_LEAVE
|
||||||
|
}
|
||||||
|
|
||||||
|
// edited messages have a submessage, use this timestamp
|
||||||
|
if ev.SubMessage != nil {
|
||||||
|
rmsg.ID = "slack " + ev.SubMessage.Timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleted message event
|
||||||
|
if ev.SubType == messageDeleted {
|
||||||
|
rmsg.Text = config.EVENT_MSG_DELETE
|
||||||
|
rmsg.Event = config.EVENT_MSG_DELETE
|
||||||
|
rmsg.ID = "slack " + ev.DeletedTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// topic change event
|
||||||
|
if ev.SubType == "channel_topic" || ev.SubType == "channel_purpose" {
|
||||||
|
rmsg.Event = config.EVENT_TOPIC_CHANGE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only deleted messages can have a empty username and text
|
||||||
|
if (rmsg.Text == "" || rmsg.Username == "") && ev.SubType != messageDeleted && len(ev.Files) == 0 {
|
||||||
|
// this is probably a webhook we couldn't resolve
|
||||||
|
if ev.BotID != "" {
|
||||||
|
return nil, fmt.Errorf("probably an incoming webhook we couldn't resolve (maybe ourselves)")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("empty message and not a deleted message")
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the attachments, so that we can send them to other slack (compatible) bridges
|
||||||
|
if len(ev.Attachments) > 0 {
|
||||||
|
rmsg.Extra["slack_attachment"] = append(rmsg.Extra["slack_attachment"], ev.Attachments)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra
|
||||||
|
if len(ev.Files) > 0 {
|
||||||
|
for _, f := range ev.Files {
|
||||||
|
err := b.handleDownloadFile(&rmsg, &f)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("download failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rmsg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendWebhook uses the configured WebhookURL to send the message
|
||||||
|
func (b *Bslack) sendWebhook(msg config.Message) (string, error) {
|
||||||
|
// skip events
|
||||||
|
if msg.Event != "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.GetBool("PrefixMessagesWithNick") {
|
||||||
|
msg.Text = msg.Username + msg.Text
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.Extra != nil {
|
||||||
|
// this sends a message only if we received a config.EVENT_FILE_FAILURE_SIZE
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
iconURL := config.GetIconURL(&rmsg, b.GetString("iconurl"))
|
||||||
|
matterMessage := matterhook.OMessage{IconURL: iconURL, Channel: msg.Channel, UserName: rmsg.Username, Text: rmsg.Text}
|
||||||
|
b.mh.Send(matterMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// webhook doesn't support file uploads, so we add the url manually
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text += " " + fi.URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have native slack_attachments add them
|
||||||
|
var attachs []slack.Attachment
|
||||||
|
if len(msg.Extra["slack_attachment"]) > 0 {
|
||||||
|
for _, attach := range msg.Extra["slack_attachment"] {
|
||||||
|
attachs = append(attachs, attach.([]slack.Attachment)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iconURL := config.GetIconURL(&msg, b.GetString("iconurl"))
|
||||||
|
matterMessage := matterhook.OMessage{IconURL: iconURL, Attachments: attachs, Channel: msg.Channel, UserName: msg.Username, Text: msg.Text}
|
||||||
|
if msg.Avatar != "" {
|
||||||
|
matterMessage.IconURL = msg.Avatar
|
||||||
|
}
|
||||||
|
err := b.mh.Send(matterMessage)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Error(err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipMessageEvent skips event that need to be skipped :-)
|
||||||
|
func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool {
|
||||||
|
if ev.SubType == "channel_leave" || ev.SubType == "channel_join" {
|
||||||
|
return b.GetBool("nosendjoinpart")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore pinned items
|
||||||
|
if ev.SubType == "pinned_item" || ev.SubType == "unpinned_item" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not send messages from ourself
|
||||||
|
if b.GetString("WebhookURL") == "" && b.GetString("WebhookBindAddress") == "" && ev.Username == b.si.User.Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip messages we made ourselves
|
||||||
|
if len(ev.Attachments) > 0 {
|
||||||
|
if ev.Attachments[0].CallbackID == "matterbridge_"+b.uuid {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !b.GetBool("EditDisable") && ev.SubMessage != nil && ev.SubMessage.ThreadTimestamp != ev.SubMessage.Timestamp {
|
||||||
|
// it seems ev.SubMessage.Edited == nil when slack unfurls
|
||||||
|
// do not forward these messages #266
|
||||||
|
if ev.SubMessage.Edited == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ev.Files) > 0 {
|
||||||
|
for _, f := range ev.Files {
|
||||||
|
// if the file is in the cache and isn't older then a minute, skip it
|
||||||
|
if ts, ok := b.cache.Get("file" + f.ID); ok && time.Since(ts.(time.Time)) < time.Minute {
|
||||||
|
b.Log.Debugf("Not downloading file id %s which we uploaded", f.ID)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
if ts, ok := b.cache.Get("filename" + f.Name); ok && time.Since(ts.(time.Time)) < time.Second*10 {
|
||||||
|
b.Log.Debugf("Not downloading file name %s which we uploaded", f.Name)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
b.Log.Debugf("Not skipping %s %s", f.Name, time.Now().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bslack) getChannelID(name string) string {
|
||||||
|
idcheck := strings.Split(name, "ID:")
|
||||||
|
if len(idcheck) > 1 {
|
||||||
|
return idcheck[1]
|
||||||
|
}
|
||||||
|
for _, channel := range b.channels {
|
||||||
|
if channel.Name == name {
|
||||||
|
return channel.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,35 +2,31 @@ package bsshchat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/shazow/ssh-chat/sshd"
|
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
"github.com/shazow/ssh-chat/sshd"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bsshchat struct {
|
type Bsshchat struct {
|
||||||
r *bufio.Scanner
|
r *bufio.Scanner
|
||||||
w io.WriteCloser
|
w io.WriteCloser
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "sshchat"
|
return &Bsshchat{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Bsshchat {
|
|
||||||
return &Bsshchat{BridgeConfig: cfg}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bsshchat) Connect() error {
|
func (b *Bsshchat) Connect() error {
|
||||||
var err error
|
var err error
|
||||||
flog.Infof("Connecting %s", b.Config.Server)
|
b.Log.Infof("Connecting %s", b.GetString("Server"))
|
||||||
go func() {
|
go func() {
|
||||||
err = sshd.ConnectShell(b.Config.Server, b.Config.Nick, func(r io.Reader, w io.WriteCloser) error {
|
err = sshd.ConnectShell(b.GetString("Server"), b.GetString("Nick"), func(r io.Reader, w io.WriteCloser) error {
|
||||||
b.r = bufio.NewScanner(r)
|
b.r = bufio.NewScanner(r)
|
||||||
b.w = w
|
b.w = w
|
||||||
b.r.Scan()
|
b.r.Scan()
|
||||||
@@ -40,10 +36,10 @@ func (b *Bsshchat) Connect() error {
|
|||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
b.Log.Debugf("%#v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,13 +56,22 @@ func (b *Bsshchat) Send(msg config.Message) (string, error) {
|
|||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.w.Write([]byte(rmsg.Username + rmsg.Text + "\r\n"))
|
||||||
|
}
|
||||||
if len(msg.Extra["file"]) > 0 {
|
if len(msg.Extra["file"]) > 0 {
|
||||||
for _, f := range msg.Extra["file"] {
|
for _, f := range msg.Extra["file"] {
|
||||||
fi := f.(config.FileInfo)
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text += fi.Comment + ": "
|
||||||
|
}
|
||||||
if fi.URL != "" {
|
if fi.URL != "" {
|
||||||
msg.Text = fi.URL
|
msg.Text = fi.URL
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text = fi.Comment + ": " + fi.URL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
b.w.Write([]byte(msg.Username + msg.Text))
|
b.w.Write([]byte(msg.Username + msg.Text))
|
||||||
}
|
}
|
||||||
@@ -86,10 +91,10 @@ func (b *Bsshchat) sshchatKeepAlive() chan bool {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
flog.Debugf("PING")
|
b.Log.Debugf("PING")
|
||||||
err := b.xc.PingC2S("", "")
|
err := b.xc.PingC2S("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("PING failed %#v", err)
|
b.Log.Debugf("PING failed %#v", err)
|
||||||
}
|
}
|
||||||
case <-done:
|
case <-done:
|
||||||
return
|
return
|
||||||
@@ -116,6 +121,10 @@ func (b *Bsshchat) handleSshChat() error {
|
|||||||
wait := true
|
wait := true
|
||||||
for {
|
for {
|
||||||
if b.r.Scan() {
|
if b.r.Scan() {
|
||||||
|
// ignore messages from ourselves
|
||||||
|
if !strings.Contains(b.r.Text(), "\033[K") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
res := strings.Split(stripPrompt(b.r.Text()), ":")
|
res := strings.Split(stripPrompt(b.r.Text()), ":")
|
||||||
if res[0] == "-> Set theme" {
|
if res[0] == "-> Set theme" {
|
||||||
wait = false
|
wait = false
|
||||||
@@ -123,7 +132,7 @@ func (b *Bsshchat) handleSshChat() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !wait {
|
if !wait {
|
||||||
flog.Debugf("message %#v", res)
|
b.Log.Debugf("<= Message %#v", res)
|
||||||
rmsg := config.Message{Username: res[0], Text: strings.Join(res[1:], ":"), Channel: "sshchat", Account: b.Account, UserID: "nick"}
|
rmsg := config.Message{Username: res[0], Text: strings.Join(res[1:], ":"), Channel: "sshchat", Account: b.Account, UserID: "nick"}
|
||||||
b.Remote <- rmsg
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package bsteam
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
"github.com/Philipp15b/go-steam"
|
"github.com/Philipp15b/go-steam"
|
||||||
"github.com/Philipp15b/go-steam/protocol/steamlang"
|
"github.com/Philipp15b/go-steam/protocol/steamlang"
|
||||||
"github.com/Philipp15b/go-steam/steamid"
|
"github.com/Philipp15b/go-steam/steamid"
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
//"io/ioutil"
|
//"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -18,31 +20,24 @@ type Bsteam struct {
|
|||||||
connected chan struct{}
|
connected chan struct{}
|
||||||
userMap map[steamid.SteamId]string
|
userMap map[steamid.SteamId]string
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "steam"
|
b := &Bsteam{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Bsteam {
|
|
||||||
b := &Bsteam{BridgeConfig: cfg}
|
|
||||||
b.userMap = make(map[steamid.SteamId]string)
|
b.userMap = make(map[steamid.SteamId]string)
|
||||||
b.connected = make(chan struct{})
|
b.connected = make(chan struct{})
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bsteam) Connect() error {
|
func (b *Bsteam) Connect() error {
|
||||||
flog.Info("Connecting")
|
b.Log.Info("Connecting")
|
||||||
b.c = steam.NewClient()
|
b.c = steam.NewClient()
|
||||||
go b.handleEvents()
|
go b.handleEvents()
|
||||||
go b.c.Connect()
|
go b.c.Connect()
|
||||||
select {
|
select {
|
||||||
case <-b.connected:
|
case <-b.connected:
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
case <-time.After(time.Second * 30):
|
case <-time.After(time.Second * 30):
|
||||||
return fmt.Errorf("connection timed out")
|
return fmt.Errorf("connection timed out")
|
||||||
}
|
}
|
||||||
@@ -73,6 +68,30 @@ func (b *Bsteam) Send(msg config.Message) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle files
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, rmsg.Username+rmsg.Text)
|
||||||
|
}
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text += fi.Comment + ": "
|
||||||
|
}
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text = fi.URL
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text = fi.Comment + ": " + fi.URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, msg.Username+msg.Text)
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, msg.Username+msg.Text)
|
b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, msg.Username+msg.Text)
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
@@ -88,18 +107,18 @@ func (b *Bsteam) getNick(id steamid.SteamId) string {
|
|||||||
|
|
||||||
func (b *Bsteam) handleEvents() {
|
func (b *Bsteam) handleEvents() {
|
||||||
myLoginInfo := new(steam.LogOnDetails)
|
myLoginInfo := new(steam.LogOnDetails)
|
||||||
myLoginInfo.Username = b.Config.Login
|
myLoginInfo.Username = b.GetString("Login")
|
||||||
myLoginInfo.Password = b.Config.Password
|
myLoginInfo.Password = b.GetString("Password")
|
||||||
myLoginInfo.AuthCode = b.Config.AuthCode
|
myLoginInfo.AuthCode = b.GetString("AuthCode")
|
||||||
// Attempt to read existing auth hash to avoid steam guard.
|
// Attempt to read existing auth hash to avoid steam guard.
|
||||||
// Maybe works
|
// Maybe works
|
||||||
//myLoginInfo.SentryFileHash, _ = ioutil.ReadFile("sentry")
|
//myLoginInfo.SentryFileHash, _ = ioutil.ReadFile("sentry")
|
||||||
for event := range b.c.Events() {
|
for event := range b.c.Events() {
|
||||||
//flog.Info(event)
|
//b.Log.Info(event)
|
||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *steam.ChatMsgEvent:
|
case *steam.ChatMsgEvent:
|
||||||
flog.Debugf("Receiving ChatMsgEvent: %#v", e)
|
b.Log.Debugf("Receiving ChatMsgEvent: %#v", e)
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", b.getNick(e.ChatterId), b.Account)
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", b.getNick(e.ChatterId), b.Account)
|
||||||
var channel int64
|
var channel int64
|
||||||
if e.ChatRoomId == 0 {
|
if e.ChatRoomId == 0 {
|
||||||
channel = int64(e.ChatterId)
|
channel = int64(e.ChatterId)
|
||||||
@@ -110,7 +129,7 @@ func (b *Bsteam) handleEvents() {
|
|||||||
msg := config.Message{Username: b.getNick(e.ChatterId), Text: e.Message, Channel: strconv.FormatInt(channel, 10), Account: b.Account, UserID: strconv.FormatInt(int64(e.ChatterId), 10)}
|
msg := config.Message{Username: b.getNick(e.ChatterId), Text: e.Message, Channel: strconv.FormatInt(channel, 10), Account: b.Account, UserID: strconv.FormatInt(int64(e.ChatterId), 10)}
|
||||||
b.Remote <- msg
|
b.Remote <- msg
|
||||||
case *steam.PersonaStateEvent:
|
case *steam.PersonaStateEvent:
|
||||||
flog.Debugf("PersonaStateEvent: %#v\n", e)
|
b.Log.Debugf("PersonaStateEvent: %#v\n", e)
|
||||||
b.Lock()
|
b.Lock()
|
||||||
b.userMap[e.FriendId] = e.Name
|
b.userMap[e.FriendId] = e.Name
|
||||||
b.Unlock()
|
b.Unlock()
|
||||||
@@ -118,47 +137,47 @@ func (b *Bsteam) handleEvents() {
|
|||||||
b.c.Auth.LogOn(myLoginInfo)
|
b.c.Auth.LogOn(myLoginInfo)
|
||||||
case *steam.MachineAuthUpdateEvent:
|
case *steam.MachineAuthUpdateEvent:
|
||||||
/*
|
/*
|
||||||
flog.Info("authupdate", e)
|
b.Log.Info("authupdate", e)
|
||||||
flog.Info("hash", e.Hash)
|
b.Log.Info("hash", e.Hash)
|
||||||
ioutil.WriteFile("sentry", e.Hash, 0666)
|
ioutil.WriteFile("sentry", e.Hash, 0666)
|
||||||
*/
|
*/
|
||||||
case *steam.LogOnFailedEvent:
|
case *steam.LogOnFailedEvent:
|
||||||
flog.Info("Logon failed", e)
|
b.Log.Info("Logon failed", e)
|
||||||
switch e.Result {
|
switch e.Result {
|
||||||
case steamlang.EResult_AccountLogonDeniedNeedTwoFactorCode:
|
case steamlang.EResult_AccountLogonDeniedNeedTwoFactorCode:
|
||||||
{
|
{
|
||||||
flog.Info("Steam guard isn't letting me in! Enter 2FA code:")
|
b.Log.Info("Steam guard isn't letting me in! Enter 2FA code:")
|
||||||
var code string
|
var code string
|
||||||
fmt.Scanf("%s", &code)
|
fmt.Scanf("%s", &code)
|
||||||
myLoginInfo.TwoFactorCode = code
|
myLoginInfo.TwoFactorCode = code
|
||||||
}
|
}
|
||||||
case steamlang.EResult_AccountLogonDenied:
|
case steamlang.EResult_AccountLogonDenied:
|
||||||
{
|
{
|
||||||
flog.Info("Steam guard isn't letting me in! Enter auth code:")
|
b.Log.Info("Steam guard isn't letting me in! Enter auth code:")
|
||||||
var code string
|
var code string
|
||||||
fmt.Scanf("%s", &code)
|
fmt.Scanf("%s", &code)
|
||||||
myLoginInfo.AuthCode = code
|
myLoginInfo.AuthCode = code
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.Errorf("LogOnFailedEvent: %#v ", e.Result)
|
b.Log.Errorf("LogOnFailedEvent: %#v ", e.Result)
|
||||||
// TODO: Handle EResult_InvalidLoginAuthCode
|
// TODO: Handle EResult_InvalidLoginAuthCode
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case *steam.LoggedOnEvent:
|
case *steam.LoggedOnEvent:
|
||||||
flog.Debugf("LoggedOnEvent: %#v", e)
|
b.Log.Debugf("LoggedOnEvent: %#v", e)
|
||||||
b.connected <- struct{}{}
|
b.connected <- struct{}{}
|
||||||
flog.Debugf("setting online")
|
b.Log.Debugf("setting online")
|
||||||
b.c.Social.SetPersonaState(steamlang.EPersonaState_Online)
|
b.c.Social.SetPersonaState(steamlang.EPersonaState_Online)
|
||||||
case *steam.DisconnectedEvent:
|
case *steam.DisconnectedEvent:
|
||||||
flog.Info("Disconnected")
|
b.Log.Info("Disconnected")
|
||||||
flog.Info("Attempting to reconnect...")
|
b.Log.Info("Attempting to reconnect...")
|
||||||
b.c.Connect()
|
b.c.Connect()
|
||||||
case steam.FatalErrorEvent:
|
case steam.FatalErrorEvent:
|
||||||
flog.Error(e)
|
b.Log.Error(e)
|
||||||
case error:
|
case error:
|
||||||
flog.Error(e)
|
b.Log.Error(e)
|
||||||
default:
|
default:
|
||||||
flog.Debugf("unknown event %#v", e)
|
b.Log.Debugf("unknown event %#v", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package btelegram
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/russross/blackfriday"
|
|
||||||
"html"
|
"html"
|
||||||
|
|
||||||
|
"github.com/russross/blackfriday"
|
||||||
)
|
)
|
||||||
|
|
||||||
type customHtml struct {
|
type customHTML struct {
|
||||||
blackfriday.Renderer
|
blackfriday.Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHtml) Paragraph(out *bytes.Buffer, text func() bool) {
|
func (options *customHTML) Paragraph(out *bytes.Buffer, text func() bool) {
|
||||||
marker := out.Len()
|
marker := out.Len()
|
||||||
|
|
||||||
if !text() {
|
if !text() {
|
||||||
@@ -20,32 +21,32 @@ func (options *customHtml) Paragraph(out *bytes.Buffer, text func() bool) {
|
|||||||
out.WriteString("\n")
|
out.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHtml) BlockCode(out *bytes.Buffer, text []byte, lang string) {
|
func (options *customHTML) BlockCode(out *bytes.Buffer, text []byte, lang string) {
|
||||||
out.WriteString("<pre>")
|
out.WriteString("<pre>")
|
||||||
|
|
||||||
out.WriteString(html.EscapeString(string(text)))
|
out.WriteString(html.EscapeString(string(text)))
|
||||||
out.WriteString("</pre>\n")
|
out.WriteString("</pre>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHtml) Header(out *bytes.Buffer, text func() bool, level int, id string) {
|
func (options *customHTML) Header(out *bytes.Buffer, text func() bool, level int, id string) {
|
||||||
options.Paragraph(out, text)
|
options.Paragraph(out, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHtml) HRule(out *bytes.Buffer) {
|
func (options *customHTML) HRule(out *bytes.Buffer) {
|
||||||
out.WriteByte('\n')
|
out.WriteByte('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHtml) BlockQuote(out *bytes.Buffer, text []byte) {
|
func (options *customHTML) BlockQuote(out *bytes.Buffer, text []byte) {
|
||||||
out.WriteString("> ")
|
out.WriteString("> ")
|
||||||
out.Write(text)
|
out.Write(text)
|
||||||
out.WriteByte('\n')
|
out.WriteByte('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHtml) List(out *bytes.Buffer, text func() bool, flags int) {
|
func (options *customHTML) List(out *bytes.Buffer, text func() bool, flags int) {
|
||||||
options.Paragraph(out, text)
|
options.Paragraph(out, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (options *customHtml) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
func (options *customHTML) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
||||||
out.WriteString("- ")
|
out.WriteString("- ")
|
||||||
out.Write(text)
|
out.Write(text)
|
||||||
out.WriteByte('\n')
|
out.WriteByte('\n')
|
||||||
@@ -53,7 +54,7 @@ func (options *customHtml) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
|||||||
|
|
||||||
func makeHTML(input string) string {
|
func makeHTML(input string) string {
|
||||||
return string(blackfriday.Markdown([]byte(input),
|
return string(blackfriday.Markdown([]byte(input),
|
||||||
&customHtml{blackfriday.HtmlRenderer(blackfriday.HTML_USE_XHTML|blackfriday.HTML_SKIP_IMAGES, "", "")},
|
&customHTML{blackfriday.HtmlRenderer(blackfriday.HTML_USE_XHTML|blackfriday.HTML_SKIP_IMAGES, "", "")},
|
||||||
blackfriday.EXTENSION_NO_INTRA_EMPHASIS|
|
blackfriday.EXTENSION_NO_INTRA_EMPHASIS|
|
||||||
blackfriday.EXTENSION_FENCED_CODE|
|
blackfriday.EXTENSION_FENCED_CODE|
|
||||||
blackfriday.EXTENSION_AUTOLINK|
|
blackfriday.EXTENSION_AUTOLINK|
|
||||||
|
|||||||
@@ -1,53 +1,49 @@
|
|||||||
package btelegram
|
package btelegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Btelegram struct {
|
type Btelegram struct {
|
||||||
c *tgbotapi.BotAPI
|
c *tgbotapi.BotAPI
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
|
avatarMap map[string]string // keep cache of userid and avatar sha
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "telegram"
|
return &Btelegram{Config: cfg, avatarMap: make(map[string]string)}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Btelegram {
|
|
||||||
return &Btelegram{BridgeConfig: cfg}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) Connect() error {
|
func (b *Btelegram) Connect() error {
|
||||||
var err error
|
var err error
|
||||||
flog.Info("Connecting")
|
b.Log.Info("Connecting")
|
||||||
b.c, err = tgbotapi.NewBotAPI(b.Config.Token)
|
b.c, err = tgbotapi.NewBotAPI(b.GetString("Token"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
b.Log.Debugf("%#v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
updates, err := b.c.GetUpdatesChan(tgbotapi.NewUpdate(0))
|
u := tgbotapi.NewUpdate(0)
|
||||||
|
u.Timeout = 60
|
||||||
|
updates, err := b.c.GetUpdatesChan(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
b.Log.Debugf("%#v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
go b.handleRecv(updates)
|
go b.handleRecv(updates)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) Disconnect() error {
|
func (b *Btelegram) Disconnect() error {
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error {
|
||||||
@@ -55,16 +51,24 @@ func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) Send(msg config.Message) (string, error) {
|
func (b *Btelegram) Send(msg config.Message) (string, error) {
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
|
// get the chatid
|
||||||
chatid, err := strconv.ParseInt(msg.Channel, 10, 64)
|
chatid, err := strconv.ParseInt(msg.Channel, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Config.MessageFormat == "HTML" {
|
// map the file SHA to our user (caches the avatar)
|
||||||
|
if msg.Event == config.EVENT_AVATAR_DOWNLOAD {
|
||||||
|
return b.cacheAvatar(&msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.GetString("MessageFormat") == "HTML" {
|
||||||
msg.Text = makeHTML(msg.Text)
|
msg.Text = makeHTML(msg.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete message
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
if msg.ID == "" {
|
if msg.ID == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
@@ -77,14 +81,38 @@ func (b *Btelegram) Send(msg config.Message) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload a file if it exists
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.sendMessage(chatid, rmsg.Username, rmsg.Text)
|
||||||
|
}
|
||||||
|
// check if we have files to upload (from slack, telegram or mattermost)
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
b.handleUploadFile(&msg, chatid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// edit the message if we have a msg ID
|
// edit the message if we have a msg ID
|
||||||
if msg.ID != "" {
|
if msg.ID != "" {
|
||||||
msgid, err := strconv.Atoi(msg.ID)
|
msgid, err := strconv.Atoi(msg.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
if strings.ToLower(b.GetString("MessageFormat")) == "htmlnick" {
|
||||||
|
b.Log.Debug("Using mode HTML - nick only")
|
||||||
|
msg.Text = html.EscapeString(msg.Text)
|
||||||
|
}
|
||||||
m := tgbotapi.NewEditMessageText(chatid, msgid, msg.Username+msg.Text)
|
m := tgbotapi.NewEditMessageText(chatid, msgid, msg.Username+msg.Text)
|
||||||
if b.Config.MessageFormat == "HTML" {
|
if b.GetString("MessageFormat") == "HTML" {
|
||||||
|
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 strings.ToLower(b.GetString("MessageFormat")) == "htmlnick" {
|
||||||
|
b.Log.Debug("Using mode HTML - nick only")
|
||||||
m.ParseMode = tgbotapi.ModeHTML
|
m.ParseMode = tgbotapi.ModeHTML
|
||||||
}
|
}
|
||||||
_, err = b.c.Send(m)
|
_, err = b.c.Send(m)
|
||||||
@@ -94,98 +122,84 @@ func (b *Btelegram) Send(msg config.Message) (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.Extra != nil {
|
// Post normal message
|
||||||
// check if we have files to upload (from slack, telegram or mattermost)
|
return b.sendMessage(chatid, msg.Username, msg.Text)
|
||||||
if len(msg.Extra["file"]) > 0 {
|
|
||||||
var c tgbotapi.Chattable
|
|
||||||
for _, f := range msg.Extra["file"] {
|
|
||||||
fi := f.(config.FileInfo)
|
|
||||||
file := tgbotapi.FileBytes{fi.Name, *fi.Data}
|
|
||||||
re := regexp.MustCompile(".(jpg|png)$")
|
|
||||||
if re.MatchString(fi.Name) {
|
|
||||||
c = tgbotapi.NewPhotoUpload(chatid, file)
|
|
||||||
} else {
|
|
||||||
c = tgbotapi.NewDocumentUpload(chatid, file)
|
|
||||||
}
|
|
||||||
_, err := b.c.Send(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("file upload failed: %#v", err)
|
|
||||||
}
|
|
||||||
if fi.Comment != "" {
|
|
||||||
b.sendMessage(chatid, msg.Username+fi.Comment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b.sendMessage(chatid, msg.Username+msg.Text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
||||||
for update := range updates {
|
for update := range updates {
|
||||||
flog.Debugf("Receiving from telegram: %#v", update.Message)
|
b.Log.Debugf("== Receiving event: %#v", update.Message)
|
||||||
var message *tgbotapi.Message
|
|
||||||
username := ""
|
|
||||||
channel := ""
|
|
||||||
text := ""
|
|
||||||
|
|
||||||
fmsg := config.Message{Extra: make(map[string][]interface{})}
|
if update.Message == nil && update.ChannelPost == nil && update.EditedMessage == nil && update.EditedChannelPost == nil {
|
||||||
|
b.Log.Error("Getting nil messages, this shouldn't happen.")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var message *tgbotapi.Message
|
||||||
|
|
||||||
|
rmsg := config.Message{Account: b.Account, Extra: make(map[string][]interface{})}
|
||||||
|
|
||||||
// handle channels
|
// handle channels
|
||||||
if update.ChannelPost != nil {
|
if update.ChannelPost != nil {
|
||||||
message = update.ChannelPost
|
message = update.ChannelPost
|
||||||
|
rmsg.Text = message.Text
|
||||||
}
|
}
|
||||||
if update.EditedChannelPost != nil && !b.Config.EditDisable {
|
|
||||||
|
// edited channel message
|
||||||
|
if update.EditedChannelPost != nil && !b.GetBool("EditDisable") {
|
||||||
message = update.EditedChannelPost
|
message = update.EditedChannelPost
|
||||||
message.Text = message.Text + b.Config.EditSuffix
|
rmsg.Text = rmsg.Text + message.Text + b.GetString("EditSuffix")
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle groups
|
// handle groups
|
||||||
if update.Message != nil {
|
if update.Message != nil {
|
||||||
message = update.Message
|
message = update.Message
|
||||||
|
rmsg.Text = message.Text
|
||||||
}
|
}
|
||||||
if update.EditedMessage != nil && !b.Config.EditDisable {
|
|
||||||
|
// edited group message
|
||||||
|
if update.EditedMessage != nil && !b.GetBool("EditDisable") {
|
||||||
message = update.EditedMessage
|
message = update.EditedMessage
|
||||||
message.Text = message.Text + b.Config.EditSuffix
|
rmsg.Text = rmsg.Text + message.Text + b.GetString("EditSuffix")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the ID's from the channel or group message
|
||||||
|
rmsg.ID = strconv.Itoa(message.MessageID)
|
||||||
|
rmsg.Channel = strconv.FormatInt(message.Chat.ID, 10)
|
||||||
|
|
||||||
|
// handle username
|
||||||
if message.From != nil {
|
if message.From != nil {
|
||||||
if b.Config.UseFirstName {
|
rmsg.UserID = strconv.Itoa(message.From.ID)
|
||||||
username = message.From.FirstName
|
if b.GetBool("UseFirstName") {
|
||||||
|
rmsg.Username = message.From.FirstName
|
||||||
}
|
}
|
||||||
if username == "" {
|
if rmsg.Username == "" {
|
||||||
username = message.From.UserName
|
rmsg.Username = message.From.UserName
|
||||||
if username == "" {
|
if rmsg.Username == "" {
|
||||||
username = message.From.FirstName
|
rmsg.Username = message.From.FirstName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text = message.Text
|
// only download avatars if we have a place to upload them (configured mediaserver)
|
||||||
channel = strconv.FormatInt(message.Chat.ID, 10)
|
if b.General.MediaServerUpload != "" {
|
||||||
|
b.handleDownloadAvatar(message.From.ID, rmsg.Channel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if username == "" {
|
// if we really didn't find a username, set it to unknown
|
||||||
username = "unknown"
|
if rmsg.Username == "" {
|
||||||
}
|
rmsg.Username = "unknown"
|
||||||
if message.Sticker != nil {
|
|
||||||
b.handleDownload(message.Sticker, &fmsg)
|
|
||||||
}
|
|
||||||
if message.Video != nil {
|
|
||||||
b.handleDownload(message.Video, &fmsg)
|
|
||||||
}
|
|
||||||
if message.Photo != nil {
|
|
||||||
b.handleDownload(message.Photo, &fmsg)
|
|
||||||
}
|
|
||||||
if message.Document != nil {
|
|
||||||
b.handleDownload(message.Document, &fmsg)
|
|
||||||
}
|
|
||||||
if message.Voice != nil {
|
|
||||||
b.handleDownload(message.Voice, &fmsg)
|
|
||||||
}
|
|
||||||
if message.Audio != nil {
|
|
||||||
b.handleDownload(message.Audio, &fmsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle any downloads
|
||||||
|
err := b.handleDownload(message, &rmsg)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("download failed: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle forwarded messages
|
||||||
if message.ForwardFrom != nil {
|
if message.ForwardFrom != nil {
|
||||||
usernameForward := ""
|
usernameForward := ""
|
||||||
if b.Config.UseFirstName {
|
if b.GetBool("UseFirstName") {
|
||||||
usernameForward = message.ForwardFrom.FirstName
|
usernameForward = message.ForwardFrom.FirstName
|
||||||
}
|
}
|
||||||
if usernameForward == "" {
|
if usernameForward == "" {
|
||||||
@@ -197,14 +211,14 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|||||||
if usernameForward == "" {
|
if usernameForward == "" {
|
||||||
usernameForward = "unknown"
|
usernameForward = "unknown"
|
||||||
}
|
}
|
||||||
text = "Forwarded from " + usernameForward + ": " + text
|
rmsg.Text = "Forwarded from " + usernameForward + ": " + rmsg.Text
|
||||||
}
|
}
|
||||||
|
|
||||||
// quote the previous message
|
// quote the previous message
|
||||||
if message.ReplyToMessage != nil {
|
if message.ReplyToMessage != nil {
|
||||||
usernameReply := ""
|
usernameReply := ""
|
||||||
if message.ReplyToMessage.From != nil {
|
if message.ReplyToMessage.From != nil {
|
||||||
if b.Config.UseFirstName {
|
if b.GetBool("UseFirstName") {
|
||||||
usernameReply = message.ReplyToMessage.From.FirstName
|
usernameReply = message.ReplyToMessage.From.FirstName
|
||||||
}
|
}
|
||||||
if usernameReply == "" {
|
if usernameReply == "" {
|
||||||
@@ -217,14 +231,21 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|||||||
if usernameReply == "" {
|
if usernameReply == "" {
|
||||||
usernameReply = "unknown"
|
usernameReply = "unknown"
|
||||||
}
|
}
|
||||||
text = text + " (re @" + usernameReply + ":" + message.ReplyToMessage.Text + ")"
|
if !b.GetBool("QuoteDisable") {
|
||||||
|
rmsg.Text = b.handleQuote(rmsg.Text, usernameReply, message.ReplyToMessage.Text)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if text != "" || len(fmsg.Extra) > 0 {
|
if rmsg.Text != "" || len(rmsg.Extra) > 0 {
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", username, b.Account)
|
rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
||||||
msg := config.Message{Username: username, Text: text, Channel: channel, Account: b.Account, UserID: strconv.Itoa(message.From.ID), ID: strconv.Itoa(message.MessageID), Extra: fmsg.Extra}
|
// channels don't have (always?) user information. see #410
|
||||||
flog.Debugf("Message is %#v", msg)
|
if message.From != nil {
|
||||||
b.Remote <- msg
|
rmsg.Avatar = helper.GetAvatar(b.avatarMap, strconv.Itoa(message.From.ID), b.General)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
||||||
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,31 +258,46 @@ func (b *Btelegram) getFileDirectURL(id string) string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) handleDownload(file interface{}, msg *config.Message) {
|
// handleDownloadAvatar downloads the avatar of userid from channel
|
||||||
size := 0
|
// sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful.
|
||||||
url := ""
|
// logs an error message if it fails
|
||||||
name := ""
|
func (b *Btelegram) handleDownloadAvatar(userid int, channel string) {
|
||||||
text := ""
|
rmsg := config.Message{Username: "system", Text: "avatar", Channel: channel, Account: b.Account, UserID: strconv.Itoa(userid), Event: config.EVENT_AVATAR_DOWNLOAD, Extra: make(map[string][]interface{})}
|
||||||
fileid := ""
|
if _, ok := b.avatarMap[strconv.Itoa(userid)]; !ok {
|
||||||
switch v := file.(type) {
|
photos, err := b.c.GetUserProfilePhotos(tgbotapi.UserProfilePhotosConfig{UserID: userid, Limit: 1})
|
||||||
case *tgbotapi.Audio:
|
if err != nil {
|
||||||
size = v.FileSize
|
b.Log.Errorf("Userprofile download failed for %#v %s", userid, err)
|
||||||
url = b.getFileDirectURL(v.FileID)
|
|
||||||
urlPart := strings.Split(url, "/")
|
|
||||||
name = urlPart[len(urlPart)-1]
|
|
||||||
text = " " + url
|
|
||||||
fileid = v.FileID
|
|
||||||
case *tgbotapi.Voice:
|
|
||||||
size = v.FileSize
|
|
||||||
url = b.getFileDirectURL(v.FileID)
|
|
||||||
urlPart := strings.Split(url, "/")
|
|
||||||
name = urlPart[len(urlPart)-1]
|
|
||||||
text = " " + url
|
|
||||||
if !strings.HasSuffix(name, ".ogg") {
|
|
||||||
name = name + ".ogg"
|
|
||||||
}
|
}
|
||||||
fileid = v.FileID
|
|
||||||
case *tgbotapi.Sticker:
|
if len(photos.Photos) > 0 {
|
||||||
|
photo := photos.Photos[0][0]
|
||||||
|
url := b.getFileDirectURL(photo.FileID)
|
||||||
|
name := strconv.Itoa(userid) + ".png"
|
||||||
|
b.Log.Debugf("trying to download %#v fileid %#v with size %#v", name, photo.FileID, photo.FileSize)
|
||||||
|
|
||||||
|
err := helper.HandleDownloadSize(b.Log, &rmsg, name, int64(photo.FileSize), b.General)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err := helper.DownloadFile(url)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("download %s failed %#v", url, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.HandleDownloadData(b.Log, &rmsg, name, rmsg.Text, "", data, b.General)
|
||||||
|
b.Remote <- rmsg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleDownloadFile handles file download
|
||||||
|
func (b *Btelegram) handleDownload(message *tgbotapi.Message, rmsg *config.Message) error {
|
||||||
|
size := 0
|
||||||
|
var url, name, text string
|
||||||
|
|
||||||
|
if message.Sticker != nil {
|
||||||
|
v := message.Sticker
|
||||||
size = v.FileSize
|
size = v.FileSize
|
||||||
url = b.getFileDirectURL(v.FileID)
|
url = b.getFileDirectURL(v.FileID)
|
||||||
urlPart := strings.Split(url, "/")
|
urlPart := strings.Split(url, "/")
|
||||||
@@ -270,49 +306,109 @@ func (b *Btelegram) handleDownload(file interface{}, msg *config.Message) {
|
|||||||
name = name + ".webp"
|
name = name + ".webp"
|
||||||
}
|
}
|
||||||
text = " " + url
|
text = " " + url
|
||||||
fileid = v.FileID
|
}
|
||||||
case *tgbotapi.Video:
|
if message.Video != nil {
|
||||||
|
v := message.Video
|
||||||
size = v.FileSize
|
size = v.FileSize
|
||||||
url = b.getFileDirectURL(v.FileID)
|
url = b.getFileDirectURL(v.FileID)
|
||||||
urlPart := strings.Split(url, "/")
|
urlPart := strings.Split(url, "/")
|
||||||
name = urlPart[len(urlPart)-1]
|
name = urlPart[len(urlPart)-1]
|
||||||
text = " " + url
|
text = " " + url
|
||||||
fileid = v.FileID
|
}
|
||||||
case *[]tgbotapi.PhotoSize:
|
if message.Photo != nil {
|
||||||
photos := *v
|
photos := *message.Photo
|
||||||
size = photos[len(photos)-1].FileSize
|
size = photos[len(photos)-1].FileSize
|
||||||
url = b.getFileDirectURL(photos[len(photos)-1].FileID)
|
url = b.getFileDirectURL(photos[len(photos)-1].FileID)
|
||||||
urlPart := strings.Split(url, "/")
|
urlPart := strings.Split(url, "/")
|
||||||
name = urlPart[len(urlPart)-1]
|
name = urlPart[len(urlPart)-1]
|
||||||
text = " " + url
|
text = " " + url
|
||||||
case *tgbotapi.Document:
|
}
|
||||||
|
if message.Document != nil {
|
||||||
|
v := message.Document
|
||||||
size = v.FileSize
|
size = v.FileSize
|
||||||
url = b.getFileDirectURL(v.FileID)
|
url = b.getFileDirectURL(v.FileID)
|
||||||
name = v.FileName
|
name = v.FileName
|
||||||
text = " " + v.FileName + " : " + url
|
text = " " + v.FileName + " : " + url
|
||||||
fileid = v.FileID
|
|
||||||
}
|
}
|
||||||
if b.Config.UseInsecureURL {
|
if message.Voice != nil {
|
||||||
msg.Text = text
|
v := message.Voice
|
||||||
return
|
size = v.FileSize
|
||||||
}
|
url = b.getFileDirectURL(v.FileID)
|
||||||
// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra
|
urlPart := strings.Split(url, "/")
|
||||||
// limit to 1MB for now
|
name = urlPart[len(urlPart)-1]
|
||||||
flog.Debugf("trying to download %#v fileid %#v with size %#v", name, fileid, size)
|
text = " " + url
|
||||||
if size <= b.General.MediaDownloadSize {
|
if !strings.HasSuffix(name, ".ogg") {
|
||||||
data, err := helper.DownloadFile(url)
|
name = name + ".ogg"
|
||||||
if err != nil {
|
|
||||||
flog.Errorf("download %s failed %#v", url, err)
|
|
||||||
} else {
|
|
||||||
flog.Debugf("download OK %#v %#v %#v", name, len(*data), len(url))
|
|
||||||
msg.Extra["file"] = append(msg.Extra["file"], config.FileInfo{Name: name, Data: data})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if message.Audio != nil {
|
||||||
|
v := message.Audio
|
||||||
|
size = v.FileSize
|
||||||
|
url = b.getFileDirectURL(v.FileID)
|
||||||
|
urlPart := strings.Split(url, "/")
|
||||||
|
name = urlPart[len(urlPart)-1]
|
||||||
|
text = " " + url
|
||||||
|
}
|
||||||
|
// if name is empty we didn't match a thing to download
|
||||||
|
if name == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// use the URL instead of native upload
|
||||||
|
if b.GetBool("UseInsecureURL") {
|
||||||
|
b.Log.Debugf("Setting message text to :%s", text)
|
||||||
|
rmsg.Text = rmsg.Text + text
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra
|
||||||
|
err := helper.HandleDownloadSize(b.Log, rmsg, name, int64(size), b.General)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data, err := helper.DownloadFile(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, "", data, b.General)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) sendMessage(chatid int64, text string) (string, error) {
|
// handleUploadFile handles native upload of files
|
||||||
m := tgbotapi.NewMessage(chatid, text)
|
func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64) (string, error) {
|
||||||
if b.Config.MessageFormat == "HTML" {
|
var c tgbotapi.Chattable
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
file := tgbotapi.FileBytes{fi.Name, *fi.Data}
|
||||||
|
re := regexp.MustCompile(".(jpg|png)$")
|
||||||
|
if re.MatchString(fi.Name) {
|
||||||
|
c = tgbotapi.NewPhotoUpload(chatid, file)
|
||||||
|
} else {
|
||||||
|
c = tgbotapi.NewDocumentUpload(chatid, file)
|
||||||
|
}
|
||||||
|
_, err := b.c.Send(c)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("file upload failed: %#v", err)
|
||||||
|
}
|
||||||
|
if fi.Comment != "" {
|
||||||
|
b.sendMessage(chatid, msg.Username, fi.Comment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Btelegram) sendMessage(chatid int64, username, text string) (string, error) {
|
||||||
|
m := tgbotapi.NewMessage(chatid, "")
|
||||||
|
m.Text = username + text
|
||||||
|
if b.GetString("MessageFormat") == "HTML" {
|
||||||
|
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 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.ParseMode = tgbotapi.ModeHTML
|
||||||
}
|
}
|
||||||
res, err := b.c.Send(m)
|
res, err := b.c.Send(m)
|
||||||
@@ -321,3 +417,25 @@ func (b *Btelegram) sendMessage(chatid int64, text string) (string, error) {
|
|||||||
}
|
}
|
||||||
return strconv.Itoa(res.MessageID), nil
|
return strconv.Itoa(res.MessageID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Btelegram) cacheAvatar(msg *config.Message) (string, error) {
|
||||||
|
fi := msg.Extra["file"][0].(config.FileInfo)
|
||||||
|
/* if we have a sha we have successfully uploaded the file to the media server,
|
||||||
|
so we can now cache the sha */
|
||||||
|
if fi.SHA != "" {
|
||||||
|
b.Log.Debugf("Added %s to %s in avatarMap", fi.SHA, msg.UserID)
|
||||||
|
b.avatarMap[msg.UserID] = fi.SHA
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Btelegram) handleQuote(message, quoteNick, quoteMessage string) string {
|
||||||
|
format := b.GetString("quoteformat")
|
||||||
|
if format == "" {
|
||||||
|
format = "{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})"
|
||||||
|
}
|
||||||
|
format = strings.Replace(format, "{MESSAGE}", message, -1)
|
||||||
|
format = strings.Replace(format, "{QUOTENICK}", quoteNick, -1)
|
||||||
|
format = strings.Replace(format, "{QUOTEMESSAGE}", quoteMessage, -1)
|
||||||
|
return format
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,43 +2,38 @@ package bxmpp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/jpillora/backoff"
|
|
||||||
"github.com/mattn/go-xmpp"
|
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
"github.com/jpillora/backoff"
|
||||||
|
"github.com/matterbridge/go-xmpp"
|
||||||
|
"github.com/rs/xid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bxmpp struct {
|
type Bxmpp struct {
|
||||||
xc *xmpp.Client
|
xc *xmpp.Client
|
||||||
xmppMap map[string]string
|
xmppMap map[string]string
|
||||||
*config.BridgeConfig
|
*bridge.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var flog *log.Entry
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
var protocol = "xmpp"
|
b := &Bxmpp{Config: cfg}
|
||||||
|
|
||||||
func init() {
|
|
||||||
flog = log.WithFields(log.Fields{"module": protocol})
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg *config.BridgeConfig) *Bxmpp {
|
|
||||||
b := &Bxmpp{BridgeConfig: cfg}
|
|
||||||
b.xmppMap = make(map[string]string)
|
b.xmppMap = make(map[string]string)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) Connect() error {
|
func (b *Bxmpp) Connect() error {
|
||||||
var err error
|
var err error
|
||||||
flog.Infof("Connecting %s", b.Config.Server)
|
b.Log.Infof("Connecting %s", b.GetString("Server"))
|
||||||
b.xc, err = b.createXMPP()
|
b.xc, err = b.createXMPP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("%#v", err)
|
b.Log.Debugf("%#v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flog.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
go func() {
|
go func() {
|
||||||
initial := true
|
initial := true
|
||||||
bf := &backoff.Backoff{
|
bf := &backoff.Backoff{
|
||||||
@@ -48,16 +43,16 @@ func (b *Bxmpp) Connect() error {
|
|||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
if initial {
|
if initial {
|
||||||
b.handleXmpp()
|
b.handleXMPP()
|
||||||
initial = false
|
initial = false
|
||||||
}
|
}
|
||||||
d := bf.Duration()
|
d := bf.Duration()
|
||||||
flog.Infof("Disconnected. Reconnecting in %s", d)
|
b.Log.Infof("Disconnected. Reconnecting in %s", d)
|
||||||
time.Sleep(d)
|
time.Sleep(d)
|
||||||
b.xc, err = b.createXMPP()
|
b.xc, err = b.createXMPP()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: "", Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: "", Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS}
|
||||||
b.handleXmpp()
|
b.handleXMPP()
|
||||||
bf.Reset()
|
bf.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,53 +65,65 @@ func (b *Bxmpp) Disconnect() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) JoinChannel(channel config.ChannelInfo) error {
|
func (b *Bxmpp) JoinChannel(channel config.ChannelInfo) error {
|
||||||
b.xc.JoinMUCNoHistory(channel.Name+"@"+b.Config.Muc, b.Config.Nick)
|
if channel.Options.Key != "" {
|
||||||
|
b.Log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name)
|
||||||
|
b.xc.JoinProtectedMUC(channel.Name+"@"+b.GetString("Muc"), b.GetString("Nick"), channel.Options.Key, xmpp.NoHistory, 0, nil)
|
||||||
|
} else {
|
||||||
|
b.xc.JoinMUCNoHistory(channel.Name+"@"+b.GetString("Muc"), b.GetString("Nick"))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) Send(msg config.Message) (string, error) {
|
func (b *Bxmpp) Send(msg config.Message) (string, error) {
|
||||||
|
var msgid = ""
|
||||||
|
var msgreplaceid = ""
|
||||||
// ignore delete messages
|
// ignore delete messages
|
||||||
if msg.Event == config.EVENT_MSG_DELETE {
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
flog.Debugf("Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
|
// Upload a file (in xmpp case send the upload URL because xmpp has no native upload support)
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: rmsg.Channel + "@" + b.GetString("Muc"), Text: rmsg.Username + rmsg.Text})
|
||||||
|
}
|
||||||
if len(msg.Extra["file"]) > 0 {
|
if len(msg.Extra["file"]) > 0 {
|
||||||
for _, f := range msg.Extra["file"] {
|
return b.handleUploadFile(&msg)
|
||||||
fi := f.(config.FileInfo)
|
|
||||||
if fi.URL != "" {
|
|
||||||
msg.Text = fi.URL
|
|
||||||
}
|
|
||||||
b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.Config.Muc, Text: msg.Username + msg.Text})
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.Config.Muc, Text: msg.Username + msg.Text})
|
msgid = xid.New().String()
|
||||||
return "", nil
|
if msg.ID != "" {
|
||||||
|
msgid = msg.ID
|
||||||
|
msgreplaceid = msg.ID
|
||||||
|
}
|
||||||
|
// Post normal message
|
||||||
|
_, err := b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.GetString("Muc"), Text: msg.Username + msg.Text, ID: msgid, ReplaceID: msgreplaceid})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return msgid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) createXMPP() (*xmpp.Client, error) {
|
func (b *Bxmpp) createXMPP() (*xmpp.Client, error) {
|
||||||
tc := new(tls.Config)
|
tc := new(tls.Config)
|
||||||
tc.InsecureSkipVerify = b.Config.SkipTLSVerify
|
tc.InsecureSkipVerify = b.GetBool("SkipTLSVerify")
|
||||||
tc.ServerName = strings.Split(b.Config.Server, ":")[0]
|
tc.ServerName = strings.Split(b.GetString("Server"), ":")[0]
|
||||||
options := xmpp.Options{
|
options := xmpp.Options{
|
||||||
Host: b.Config.Server,
|
Host: b.GetString("Server"),
|
||||||
User: b.Config.Jid,
|
User: b.GetString("Jid"),
|
||||||
Password: b.Config.Password,
|
Password: b.GetString("Password"),
|
||||||
NoTLS: true,
|
NoTLS: true,
|
||||||
StartTLS: true,
|
StartTLS: true,
|
||||||
TLSConfig: tc,
|
TLSConfig: tc,
|
||||||
|
Debug: b.GetBool("debug"),
|
||||||
//StartTLS: false,
|
Logger: b.Log.Writer(),
|
||||||
Debug: true,
|
|
||||||
Session: true,
|
Session: true,
|
||||||
Status: "",
|
Status: "",
|
||||||
StatusMessage: "",
|
StatusMessage: "",
|
||||||
Resource: "",
|
Resource: "",
|
||||||
InsecureAllowUnencryptedAuth: false,
|
InsecureAllowUnencryptedAuth: false,
|
||||||
//InsecureAllowUnencryptedAuth: true,
|
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
b.xc, err = options.NewClient()
|
b.xc, err = options.NewClient()
|
||||||
@@ -131,10 +138,10 @@ func (b *Bxmpp) xmppKeepAlive() chan bool {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
flog.Debugf("PING")
|
b.Log.Debugf("PING")
|
||||||
err := b.xc.PingC2S("", "")
|
err := b.xc.PingC2S("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flog.Debugf("PING failed %#v", err)
|
b.Log.Debugf("PING failed %#v", err)
|
||||||
}
|
}
|
||||||
case <-done:
|
case <-done:
|
||||||
return
|
return
|
||||||
@@ -144,11 +151,11 @@ func (b *Bxmpp) xmppKeepAlive() chan bool {
|
|||||||
return done
|
return done
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bxmpp) handleXmpp() error {
|
func (b *Bxmpp) handleXMPP() error {
|
||||||
var ok bool
|
var ok bool
|
||||||
|
var msgid string
|
||||||
done := b.xmppKeepAlive()
|
done := b.xmppKeepAlive()
|
||||||
defer close(done)
|
defer close(done)
|
||||||
nodelay := time.Time{}
|
|
||||||
for {
|
for {
|
||||||
m, err := b.xc.Recv()
|
m, err := b.xc.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -156,25 +163,26 @@ func (b *Bxmpp) handleXmpp() error {
|
|||||||
}
|
}
|
||||||
switch v := m.(type) {
|
switch v := m.(type) {
|
||||||
case xmpp.Chat:
|
case xmpp.Chat:
|
||||||
var channel, nick string
|
|
||||||
if v.Type == "groupchat" {
|
if v.Type == "groupchat" {
|
||||||
s := strings.Split(v.Remote, "@")
|
b.Log.Debugf("== Receiving %#v", v)
|
||||||
if len(s) >= 2 {
|
// skip invalid messages
|
||||||
channel = s[0]
|
if b.skipMessage(v) {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
s = strings.Split(s[1], "/")
|
msgid = v.ID
|
||||||
if len(s) == 2 {
|
if v.ReplaceID != "" {
|
||||||
nick = s[1]
|
msgid = v.ReplaceID
|
||||||
}
|
}
|
||||||
if nick != b.Config.Nick && v.Stamp == nodelay && v.Text != "" {
|
rmsg := config.Message{Username: b.parseNick(v.Remote), Text: v.Text, Channel: b.parseChannel(v.Remote), Account: b.Account, UserID: v.Remote, ID: msgid}
|
||||||
rmsg := config.Message{Username: nick, Text: v.Text, Channel: channel, Account: b.Account, UserID: v.Remote}
|
|
||||||
rmsg.Text, ok = b.replaceAction(rmsg.Text)
|
// check if we have an action event
|
||||||
if ok {
|
rmsg.Text, ok = b.replaceAction(rmsg.Text)
|
||||||
rmsg.Event = config.EVENT_USER_ACTION
|
if ok {
|
||||||
}
|
rmsg.Event = config.EVENT_USER_ACTION
|
||||||
flog.Debugf("Sending message from %s on %s to gateway", nick, b.Account)
|
|
||||||
b.Remote <- rmsg
|
|
||||||
}
|
}
|
||||||
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
||||||
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
case xmpp.Presence:
|
case xmpp.Presence:
|
||||||
// do nothing
|
// do nothing
|
||||||
@@ -188,3 +196,71 @@ func (b *Bxmpp) replaceAction(text string) (string, bool) {
|
|||||||
}
|
}
|
||||||
return text, false
|
return text, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleUploadFile handles native upload of files
|
||||||
|
func (b *Bxmpp) handleUploadFile(msg *config.Message) (string, error) {
|
||||||
|
var urldesc = ""
|
||||||
|
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text += fi.Comment + ": "
|
||||||
|
}
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text = fi.URL
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text = fi.Comment + ": " + fi.URL
|
||||||
|
urldesc = fi.Comment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.GetString("Muc"), Text: msg.Username + msg.Text})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if fi.URL != "" {
|
||||||
|
b.xc.SendOOB(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.GetString("Muc"), Ooburl: fi.URL, Oobdesc: urldesc})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bxmpp) parseNick(remote string) string {
|
||||||
|
s := strings.Split(remote, "@")
|
||||||
|
if len(s) > 0 {
|
||||||
|
s = strings.Split(s[1], "/")
|
||||||
|
if len(s) == 2 {
|
||||||
|
return s[1] // nick
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bxmpp) parseChannel(remote string) string {
|
||||||
|
s := strings.Split(remote, "@")
|
||||||
|
if len(s) >= 2 {
|
||||||
|
return s[0] // channel
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipMessage skips messages that need to be skipped
|
||||||
|
func (b *Bxmpp) skipMessage(message xmpp.Chat) bool {
|
||||||
|
// skip messages from ourselves
|
||||||
|
if b.parseNick(message.Remote) == b.GetString("Nick") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip empty messages
|
||||||
|
if message.Text == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip subject messages
|
||||||
|
if strings.Contains(message.Text, "</subject>") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip delayed messages
|
||||||
|
t := time.Time{}
|
||||||
|
return message.Stamp != t
|
||||||
|
}
|
||||||
|
|||||||
170
bridge/zulip/zulip.go
Normal file
170
bridge/zulip/zulip.go
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
package bzulip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
gzb "github.com/matterbridge/gozulipbot"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Bzulip struct {
|
||||||
|
q *gzb.Queue
|
||||||
|
bot *gzb.Bot
|
||||||
|
streams map[int]string
|
||||||
|
*bridge.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
|
return &Bzulip{Config: cfg, streams: make(map[int]string)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) Connect() error {
|
||||||
|
bot := gzb.Bot{APIKey: b.GetString("token"), APIURL: b.GetString("server") + "/api/v1/", Email: b.GetString("login")}
|
||||||
|
bot.Init()
|
||||||
|
q, err := bot.RegisterAll()
|
||||||
|
b.q = q
|
||||||
|
b.bot = &bot
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("Connect() %#v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// init stream
|
||||||
|
b.getChannel(0)
|
||||||
|
b.Log.Info("Connection succeeded")
|
||||||
|
go b.handleQueue()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) Disconnect() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) JoinChannel(channel config.ChannelInfo) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) Send(msg config.Message) (string, error) {
|
||||||
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
|
// Delete message
|
||||||
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
|
if msg.ID == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
_, err := b.bot.UpdateMessage(msg.ID, "")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload a file if it exists
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.sendMessage(rmsg)
|
||||||
|
}
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
return b.handleUploadFile(&msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// edit the message if we have a msg ID
|
||||||
|
if msg.ID != "" {
|
||||||
|
_, err := b.bot.UpdateMessage(msg.ID, msg.Username+msg.Text)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post normal message
|
||||||
|
return b.sendMessage(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) getChannel(id int) string {
|
||||||
|
if name, ok := b.streams[id]; ok {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
streams, err := b.bot.GetRawStreams()
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("getChannel: %#v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
for _, stream := range streams.Streams {
|
||||||
|
b.streams[stream.StreamID] = stream.Name
|
||||||
|
}
|
||||||
|
if name, ok := b.streams[id]; ok {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) handleQueue() error {
|
||||||
|
for {
|
||||||
|
messages, _ := b.q.GetEvents()
|
||||||
|
for _, m := range messages {
|
||||||
|
b.Log.Debugf("== Receiving %#v", m)
|
||||||
|
// ignore our own messages
|
||||||
|
if m.SenderEmail == b.GetString("login") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rmsg := config.Message{Username: m.SenderFullName, Text: m.Content, Channel: b.getChannel(m.StreamID), Account: b.Account, UserID: strconv.Itoa(m.SenderID), Avatar: m.AvatarURL}
|
||||||
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
||||||
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
|
b.Remote <- rmsg
|
||||||
|
b.q.LastEventID = m.ID
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) sendMessage(msg config.Message) (string, error) {
|
||||||
|
topic := "matterbridge"
|
||||||
|
if b.GetString("topic") != "" {
|
||||||
|
topic = b.GetString("topic")
|
||||||
|
}
|
||||||
|
m := gzb.Message{
|
||||||
|
Stream: msg.Channel,
|
||||||
|
Topic: topic,
|
||||||
|
Content: msg.Username + msg.Text,
|
||||||
|
}
|
||||||
|
resp, err := b.bot.Message(m)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
res, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var jr struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(res, &jr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strconv.Itoa(jr.ID), nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) handleUploadFile(msg *config.Message) (string, error) {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text += fi.Comment + ": "
|
||||||
|
}
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text = fi.URL
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text = fi.Comment + ": " + fi.URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := b.sendMessage(*msg)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
162
changelog.md
162
changelog.md
@@ -1,3 +1,165 @@
|
|||||||
|
# v1.11.3
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* mattermost: fix panic when using webhooks #491
|
||||||
|
* slack: fix issues regarding API changes and lots of channels #489
|
||||||
|
* irc: fix rejoin on kick problem #488
|
||||||
|
|
||||||
|
# v1.11.2
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* slack: fix slack API changes regarding to files/images
|
||||||
|
|
||||||
|
# v1.11.1
|
||||||
|
|
||||||
|
## New features
|
||||||
|
* slack: Add support for slack channels by ID. Closes #436
|
||||||
|
* discord: Clip too long messages sent to discord (discord). Closes #440
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* general: fix possible panic on downloads that are too big #448
|
||||||
|
* general: Fix avatar uploads to work with MediaDownloadPath. Closes #454
|
||||||
|
* discord: allow receiving of topic changes/channel leave/joins from other bridges through the webhook
|
||||||
|
* discord: Add a space before url in file uploads (discord). Closes #461
|
||||||
|
* discord: Skip empty messages being sent with the webhook (discord). #469
|
||||||
|
* mattermost: Use nickname instead of username if defined (mattermost). Closes #452
|
||||||
|
* irc: Stop numbers being stripped after non-color control codes (irc) (#465)
|
||||||
|
* slack: Use UserID to look for avatar instead of username (slack). Closes #472
|
||||||
|
|
||||||
|
# v1.11.0
|
||||||
|
|
||||||
|
## New features
|
||||||
|
* general: Add config option MediaDownloadPath (#443). See `MediaDownloadPath` in matterbridge.toml.sample
|
||||||
|
* general: Add MediaDownloadBlacklist option. Closes #442. See `MediaDownloadBlacklist` in matterbridge.toml.sample
|
||||||
|
* xmpp: Add channel password support for XMPP (#451)
|
||||||
|
* xmpp: Add message correction support for XMPP (#437)
|
||||||
|
* telegram: Add support for MessageFormat=htmlnick (telegram). #444
|
||||||
|
* mattermost: Add support for mattermost 5.x
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
* slack: Add Title from attachment slack message (#446)
|
||||||
|
* irc: Prevent white or black color codes (irc) (#434)
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* slack: Fix regexp in replaceMention (slack). (#435)
|
||||||
|
* irc: Reconnect on quit. (irc) See #431 (#445)
|
||||||
|
* sshchat: Ignore messages from ourself. (sshchat) Closes #439
|
||||||
|
|
||||||
|
# v1.10.1
|
||||||
|
## New features
|
||||||
|
* irc: Colorize username sent to IRC using its crc32 IEEE checksum (#423). See `ColorNicks` in matterbridge.toml.sample
|
||||||
|
* irc: Add support for CJK to/from utf-8 (irc). #400
|
||||||
|
* telegram: Add QuoteFormat option (telegram). Closes #413. See `QuoteFormat` in matterbridge.toml.sample
|
||||||
|
* xmpp: Send attached files to XMPP in different message with OOB data and without body (#421)
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* general: updated irc/xmpp/telegram libraries
|
||||||
|
* mattermost/slack/rocketchat: Fix iconurl regression. Closes #430
|
||||||
|
* mattermost/slack: Use uuid instead of userid. Fixes #429
|
||||||
|
* slack: Avatar spoofing from Slack to Discord with uppercase in nick doesn't work (#433)
|
||||||
|
* irc: Fix format string bug (irc) (#428)
|
||||||
|
|
||||||
|
# v1.10.0
|
||||||
|
## New features
|
||||||
|
* general: Add support for reloading all settings automatically after changing config except connection and gateway configuration. Closes #373
|
||||||
|
* zulip: New protocol support added (https://zulipchat.com)
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
* general: Handle file comment better
|
||||||
|
* steam: Handle file uploads to mediaserver (steam)
|
||||||
|
* slack: Properly set Slack user who initiated slash command (#394)
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* general: Use only alphanumeric for file uploads to mediaserver. Closes #416
|
||||||
|
* general: Fix crash on invalid filenames
|
||||||
|
* general: Fix regression in ReplaceMessages and ReplaceNicks. Closes #407
|
||||||
|
* telegram: Fix possible nil when using channels (telegram). #410
|
||||||
|
* telegram: Fix panic (telegram). Closes #410
|
||||||
|
* telegram: Handle channel posts correctly
|
||||||
|
* mattermost: Update GetFileLinks to API_V4
|
||||||
|
|
||||||
|
# v1.9.1
|
||||||
|
## New features
|
||||||
|
* telegram: Add QuoteDisable option (telegram). Closes #399. See QuoteDisable in matterbridge.toml.sample
|
||||||
|
## Enhancements
|
||||||
|
* discord: Send mediaserver link to Discord in Webhook mode (discord) (#405)
|
||||||
|
* mattermost: Print list of valid team names when team not found (#390)
|
||||||
|
* slack: Strip markdown URLs with blank text (slack) (#392)
|
||||||
|
## Bugfix
|
||||||
|
* slack/mattermost: Make our callbackid more unique. Fixes issue with running multiple matterbridge on the same channel (slack,mattermost)
|
||||||
|
* telegram: fix newlines in multiline messages #399
|
||||||
|
* telegram: Revert #378
|
||||||
|
|
||||||
|
# v1.9.0 (the refactor release)
|
||||||
|
## New features
|
||||||
|
* general: better debug messages
|
||||||
|
* general: better support for environment variables override
|
||||||
|
* general: Ability to disable sending join/leave messages to other gateways. #382
|
||||||
|
* slack: Allow Slack @usergroups to be parsed as human-friendly names #379
|
||||||
|
* slack: Provide better context for shared posts from Slack<=>Slack enhancement #369
|
||||||
|
* telegram: Convert nicks automatically into HTML when MessageFormat is set to HTML #378
|
||||||
|
* irc: Add DebugLevel option
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* slack: Ignore restricted_action on channel join (slack). Closes #387
|
||||||
|
* slack: Add slack attachment support to matterhook
|
||||||
|
* slack: Update userlist on join (slack). Closes #372
|
||||||
|
|
||||||
|
# v1.8.0
|
||||||
|
## New features
|
||||||
|
* general: Send chat notification if media is too big to be re-uploaded to MediaServer. See #359
|
||||||
|
* general: Download (and upload) avatar images from mattermost and telegram when mediaserver is configured. Closes #362
|
||||||
|
* general: Add label support in RemoteNickFormat
|
||||||
|
* general: Prettier info/debug log output
|
||||||
|
* mattermost: Download files and reupload to supported bridges (mattermost). Closes #357
|
||||||
|
* slack: Add ShowTopicChange option. Allow/disable topic change messages (currently only from slack). Closes #353
|
||||||
|
* slack: Add support for file comments (slack). Closes #346
|
||||||
|
* telegram: Add comment to file upload from telegram. Show comments on all bridges. Closes #358
|
||||||
|
* telegram: Add markdown support (telegram). #355
|
||||||
|
* api: Give api access to whole config.Message (and events). Closes #374
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* discord: Check for a valid WebhookURL (discord). Closes #367
|
||||||
|
* discord: Fix role mention replace issues
|
||||||
|
* irc: Truncate messages sent to IRC based on byte count (#368)
|
||||||
|
* mattermost: Add file download urls also to mattermost webhooks #356
|
||||||
|
* telegram: Fix panic on nil messages (telegram). Closes #366
|
||||||
|
* telegram: Fix the UseInsecureURL text (telegram). Closes #184
|
||||||
|
|
||||||
|
# v1.7.1
|
||||||
|
## Bugfix
|
||||||
|
* telegram: Enable Long Polling for Telegram. Reduces bandwidth consumption. (#350)
|
||||||
|
|
||||||
|
# v1.7.0
|
||||||
|
## New features
|
||||||
|
* matrix: Add support for deleting messages from/to matrix (matrix). Closes #320
|
||||||
|
* xmpp: Ignore <subject> messages (xmpp). #272
|
||||||
|
* irc: Add twitch support (irc) to README / wiki
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
* general: Change RemoteNickFormat replacement order. Closes #336
|
||||||
|
* general: Make edits/delete work for bridges that gets reused. Closes #342
|
||||||
|
* general: Lowercase irc channels in config. Closes #348
|
||||||
|
* matrix: Fix possible panics (matrix). Closes #333
|
||||||
|
* matrix: Add an extension to images without one (matrix). #331
|
||||||
|
* api: Obey the Gateway value from the json (api). Closes #344
|
||||||
|
* xmpp: Print only debug messages when specified (xmpp). Closes #345
|
||||||
|
* xmpp: Allow xmpp to receive the extra messages (file uploads) when text is empty. #295
|
||||||
|
|
||||||
|
# v1.6.3
|
||||||
|
## Bugfix
|
||||||
|
* slack: Fix connection issues
|
||||||
|
* slack: Add more debug messages
|
||||||
|
* irc: Convert received IRC channel names to lowercase. Fixes #329 (#330)
|
||||||
|
|
||||||
|
# v1.6.2
|
||||||
|
## Bugfix
|
||||||
|
* mattermost: Crashes while connecting to Mattermost (regression). Closes #327
|
||||||
|
|
||||||
|
# v1.6.1
|
||||||
|
## Bugfix
|
||||||
|
* general: Display of nicks not longer working (regression). Closes #323
|
||||||
|
|
||||||
# v1.6.0
|
# v1.6.0
|
||||||
## New features
|
## New features
|
||||||
* sshchat: New protocol support added (https://github.com/shazow/ssh-chat)
|
* sshchat: New protocol support added (https://github.com/shazow/ssh-chat)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
go version |grep go1.9 || exit
|
go version |grep go1.10 || exit
|
||||||
VERSION=$(git describe --tags)
|
VERSION=$(git describe --tags)
|
||||||
mkdir ci/binaries
|
mkdir ci/binaries
|
||||||
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-windows-amd64.exe
|
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-windows-amd64.exe
|
||||||
|
|||||||
11
docker/arm/Dockerfile
Normal file
11
docker/arm/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM cmosh/alpine-arm:edge
|
||||||
|
ENTRYPOINT ["/bin/matterbridge"]
|
||||||
|
|
||||||
|
COPY . /go/src/github.com/42wim/matterbridge
|
||||||
|
RUN apk update && apk add go git gcc musl-dev ca-certificates \
|
||||||
|
&& cd /go/src/github.com/42wim/matterbridge \
|
||||||
|
&& export GOPATH=/go \
|
||||||
|
&& go get \
|
||||||
|
&& go build -x -ldflags "-X main.githash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge \
|
||||||
|
&& rm -rf /go \
|
||||||
|
&& apk del --purge git go gcc musl-dev
|
||||||
@@ -3,17 +3,35 @@ package gateway
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/api"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
log "github.com/Sirupsen/logrus"
|
bdiscord "github.com/42wim/matterbridge/bridge/discord"
|
||||||
|
bgitter "github.com/42wim/matterbridge/bridge/gitter"
|
||||||
|
birc "github.com/42wim/matterbridge/bridge/irc"
|
||||||
|
bmatrix "github.com/42wim/matterbridge/bridge/matrix"
|
||||||
|
bmattermost "github.com/42wim/matterbridge/bridge/mattermost"
|
||||||
|
brocketchat "github.com/42wim/matterbridge/bridge/rocketchat"
|
||||||
|
bslack "github.com/42wim/matterbridge/bridge/slack"
|
||||||
|
bsshchat "github.com/42wim/matterbridge/bridge/sshchat"
|
||||||
|
bsteam "github.com/42wim/matterbridge/bridge/steam"
|
||||||
|
btelegram "github.com/42wim/matterbridge/bridge/telegram"
|
||||||
|
bxmpp "github.com/42wim/matterbridge/bridge/xmpp"
|
||||||
|
bzulip "github.com/42wim/matterbridge/bridge/zulip"
|
||||||
|
"github.com/hashicorp/golang-lru"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"github.com/hashicorp/golang-lru"
|
"path/filepath"
|
||||||
"github.com/peterhellberg/emojilib"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/peterhellberg/emojilib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Gateway struct {
|
type Gateway struct {
|
||||||
@@ -29,8 +47,31 @@ type Gateway struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BrMsgID struct {
|
type BrMsgID struct {
|
||||||
br *bridge.Bridge
|
br *bridge.Bridge
|
||||||
ID string
|
ID string
|
||||||
|
ChannelID string
|
||||||
|
}
|
||||||
|
|
||||||
|
var flog *log.Entry
|
||||||
|
|
||||||
|
var bridgeMap = map[string]bridge.Factory{
|
||||||
|
"api": api.New,
|
||||||
|
"discord": bdiscord.New,
|
||||||
|
"gitter": bgitter.New,
|
||||||
|
"irc": birc.New,
|
||||||
|
"mattermost": bmattermost.New,
|
||||||
|
"matrix": bmatrix.New,
|
||||||
|
"rocketchat": brocketchat.New,
|
||||||
|
"slack": bslack.New,
|
||||||
|
"sshchat": bsshchat.New,
|
||||||
|
"steam": bsteam.New,
|
||||||
|
"telegram": btelegram.New,
|
||||||
|
"xmpp": bxmpp.New,
|
||||||
|
"zulip": bzulip.New,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flog = log.WithFields(log.Fields{"prefix": "gateway"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg config.Gateway, r *Router) *Gateway {
|
func New(cfg config.Gateway, r *Router) *Gateway {
|
||||||
@@ -45,7 +86,14 @@ func New(cfg config.Gateway, r *Router) *Gateway {
|
|||||||
func (gw *Gateway) AddBridge(cfg *config.Bridge) error {
|
func (gw *Gateway) AddBridge(cfg *config.Bridge) error {
|
||||||
br := gw.Router.getBridge(cfg.Account)
|
br := gw.Router.getBridge(cfg.Account)
|
||||||
if br == nil {
|
if br == nil {
|
||||||
br = bridge.New(gw.Config, cfg, gw.Message)
|
br = bridge.New(cfg)
|
||||||
|
br.Config = gw.Router.Config
|
||||||
|
br.General = &gw.General
|
||||||
|
// set logging
|
||||||
|
br.Log = log.WithFields(log.Fields{"prefix": "bridge"})
|
||||||
|
brconfig := &bridge.Config{Remote: gw.Message, Log: log.WithFields(log.Fields{"prefix": br.Protocol}), Bridge: br}
|
||||||
|
// add the actual bridger for this protocol to this bridge using the bridgeMap
|
||||||
|
br.Bridger = bridgeMap[br.Protocol](brconfig)
|
||||||
}
|
}
|
||||||
gw.mapChannelsToBridge(br)
|
gw.mapChannelsToBridge(br)
|
||||||
gw.Bridges[cfg.Account] = br
|
gw.Bridges[cfg.Account] = br
|
||||||
@@ -77,10 +125,10 @@ func (gw *Gateway) reconnectBridge(br *bridge.Bridge) {
|
|||||||
br.Disconnect()
|
br.Disconnect()
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
RECONNECT:
|
RECONNECT:
|
||||||
log.Infof("Reconnecting %s", br.Account)
|
flog.Infof("Reconnecting %s", br.Account)
|
||||||
err := br.Connect()
|
err := br.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Reconnection failed: %s. Trying again in 60 seconds", err)
|
flog.Errorf("Reconnection failed: %s. Trying again in 60 seconds", err)
|
||||||
time.Sleep(time.Second * 60)
|
time.Sleep(time.Second * 60)
|
||||||
goto RECONNECT
|
goto RECONNECT
|
||||||
}
|
}
|
||||||
@@ -93,6 +141,10 @@ func (gw *Gateway) mapChannelConfig(cfg []config.Bridge, direction string) {
|
|||||||
if isApi(br.Account) {
|
if isApi(br.Account) {
|
||||||
br.Channel = "api"
|
br.Channel = "api"
|
||||||
}
|
}
|
||||||
|
// make sure to lowercase irc channels in config #348
|
||||||
|
if strings.HasPrefix(br.Account, "irc.") {
|
||||||
|
br.Channel = strings.ToLower(br.Channel)
|
||||||
|
}
|
||||||
ID := br.Channel + br.Account
|
ID := br.Channel + br.Account
|
||||||
if _, ok := gw.Channels[ID]; !ok {
|
if _, ok := gw.Channels[ID]; !ok {
|
||||||
channel := &config.ChannelInfo{Name: br.Channel, Direction: direction, ID: ID, Options: br.Options, Account: br.Account,
|
channel := &config.ChannelInfo{Name: br.Channel, Direction: direction, ID: ID, Options: br.Options, Account: br.Account,
|
||||||
@@ -118,6 +170,12 @@ func (gw *Gateway) mapChannels() error {
|
|||||||
|
|
||||||
func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []config.ChannelInfo {
|
func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []config.ChannelInfo {
|
||||||
var channels []config.ChannelInfo
|
var channels []config.ChannelInfo
|
||||||
|
|
||||||
|
// for messages received from the api check that the gateway is the specified one
|
||||||
|
if msg.Protocol == "api" && gw.Name != msg.Gateway {
|
||||||
|
return channels
|
||||||
|
}
|
||||||
|
|
||||||
// if source channel is in only, do nothing
|
// if source channel is in only, do nothing
|
||||||
for _, channel := range gw.Channels {
|
for _, channel := range gw.Channels {
|
||||||
// lookup the channel from the message
|
// lookup the channel from the message
|
||||||
@@ -134,7 +192,7 @@ func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []con
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// do samechannelgateway logic
|
// do samechannelgateway flogic
|
||||||
if channel.SameChannel[msg.Gateway] {
|
if channel.SameChannel[msg.Gateway] {
|
||||||
if msg.Channel == channel.Name && msg.Account != dest.Account {
|
if msg.Channel == channel.Name && msg.Account != dest.Account {
|
||||||
channels = append(channels, *channel)
|
channels = append(channels, *channel)
|
||||||
@@ -151,38 +209,55 @@ func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []con
|
|||||||
func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrMsgID {
|
func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrMsgID {
|
||||||
var brMsgIDs []*BrMsgID
|
var brMsgIDs []*BrMsgID
|
||||||
|
|
||||||
// TODO refactor
|
// if we have an attached file, or other info
|
||||||
// only slack now, check will have to be done in the different bridges.
|
|
||||||
// we need to check if we can't use fallback or text in other bridges
|
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
if dest.Protocol != "discord" &&
|
if len(msg.Extra[config.EVENT_FILE_FAILURE_SIZE]) != 0 {
|
||||||
dest.Protocol != "slack" &&
|
|
||||||
dest.Protocol != "mattermost" &&
|
|
||||||
dest.Protocol != "telegram" &&
|
|
||||||
dest.Protocol != "matrix" {
|
|
||||||
if msg.Text == "" {
|
if msg.Text == "" {
|
||||||
return brMsgIDs
|
return brMsgIDs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// only relay join/part when configged
|
|
||||||
if msg.Event == config.EVENT_JOIN_LEAVE && !gw.Bridges[dest.Account].Config.ShowJoinPart {
|
// Avatar downloads are only relevant for telegram and mattermost for now
|
||||||
|
if msg.Event == config.EVENT_AVATAR_DOWNLOAD {
|
||||||
|
if dest.Protocol != "mattermost" &&
|
||||||
|
dest.Protocol != "telegram" {
|
||||||
|
return brMsgIDs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only relay join/part when configured
|
||||||
|
if msg.Event == config.EVENT_JOIN_LEAVE && !gw.Bridges[dest.Account].GetBool("ShowJoinPart") {
|
||||||
return brMsgIDs
|
return brMsgIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only relay topic change when configured
|
||||||
|
if msg.Event == config.EVENT_TOPIC_CHANGE && !gw.Bridges[dest.Account].GetBool("ShowTopicChange") {
|
||||||
|
return brMsgIDs
|
||||||
|
}
|
||||||
|
|
||||||
// broadcast to every out channel (irc QUIT)
|
// broadcast to every out channel (irc QUIT)
|
||||||
if msg.Channel == "" && msg.Event != config.EVENT_JOIN_LEAVE {
|
if msg.Channel == "" && msg.Event != config.EVENT_JOIN_LEAVE {
|
||||||
log.Debug("empty channel")
|
flog.Debug("empty channel")
|
||||||
return brMsgIDs
|
return brMsgIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
originchannel := msg.Channel
|
originchannel := msg.Channel
|
||||||
origmsg := msg
|
origmsg := msg
|
||||||
channels := gw.getDestChannel(&msg, *dest)
|
channels := gw.getDestChannel(&msg, *dest)
|
||||||
for _, channel := range channels {
|
for _, channel := range channels {
|
||||||
// do not send to ourself
|
// Only send the avatar download event to ourselves.
|
||||||
if channel.ID == getChannelID(origmsg) {
|
if msg.Event == config.EVENT_AVATAR_DOWNLOAD {
|
||||||
continue
|
if channel.ID != getChannelID(origmsg) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// do not send to ourself for any other event
|
||||||
|
if channel.ID == getChannelID(origmsg) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel.Name)
|
flog.Debugf("=> Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel.Name)
|
||||||
msg.Channel = channel.Name
|
msg.Channel = channel.Name
|
||||||
msg.Avatar = gw.modifyAvatar(origmsg, dest)
|
msg.Avatar = gw.modifyAvatar(origmsg, dest)
|
||||||
msg.Username = gw.modifyUsername(origmsg, dest)
|
msg.Username = gw.modifyUsername(origmsg, dest)
|
||||||
@@ -190,7 +265,9 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrM
|
|||||||
if res, ok := gw.Messages.Get(origmsg.ID); ok {
|
if res, ok := gw.Messages.Get(origmsg.ID); ok {
|
||||||
IDs := res.([]*BrMsgID)
|
IDs := res.([]*BrMsgID)
|
||||||
for _, id := range IDs {
|
for _, id := range IDs {
|
||||||
if dest.Protocol == id.br.Protocol {
|
// check protocol, bridge name and channelname
|
||||||
|
// for people that reuse the same bridge multiple times. see #342
|
||||||
|
if dest.Protocol == id.br.Protocol && dest.Name == id.br.Name && channel.ID == id.ChannelID {
|
||||||
msg.ID = id.ID
|
msg.ID = id.ID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,11 +278,12 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrM
|
|||||||
}
|
}
|
||||||
mID, err := dest.Send(msg)
|
mID, err := dest.Send(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
flog.Error(err)
|
||||||
}
|
}
|
||||||
// append the message ID (mID) from this bridge (dest) to our brMsgIDs slice
|
// append the message ID (mID) from this bridge (dest) to our brMsgIDs slice
|
||||||
if mID != "" {
|
if mID != "" {
|
||||||
brMsgIDs = append(brMsgIDs, &BrMsgID{dest, mID})
|
flog.Debugf("mID %s: %s", dest.Account, mID)
|
||||||
|
brMsgIDs = append(brMsgIDs, &BrMsgID{dest, mID, channel.ID})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return brMsgIDs
|
return brMsgIDs
|
||||||
@@ -216,30 +294,39 @@ func (gw *Gateway) ignoreMessage(msg *config.Message) bool {
|
|||||||
if _, ok := gw.Bridges[msg.Account]; !ok {
|
if _, ok := gw.Bridges[msg.Account]; !ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if we need to ignore a empty message
|
||||||
if msg.Text == "" {
|
if msg.Text == "" {
|
||||||
// we have an attachment or actual bytes
|
// we have an attachment or actual bytes, do not ignore
|
||||||
if msg.Extra != nil && (msg.Extra["attachments"] != nil || len(msg.Extra["file"]) > 0) {
|
if msg.Extra != nil &&
|
||||||
|
(msg.Extra["attachments"] != nil ||
|
||||||
|
len(msg.Extra["file"]) > 0 ||
|
||||||
|
len(msg.Extra[config.EVENT_FILE_FAILURE_SIZE]) > 0) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
log.Debugf("ignoring empty message %#v from %s", msg, msg.Account)
|
flog.Debugf("ignoring empty message %#v from %s", msg, msg.Account)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for _, entry := range strings.Fields(gw.Bridges[msg.Account].Config.IgnoreNicks) {
|
|
||||||
|
// is the username in IgnoreNicks field
|
||||||
|
for _, entry := range strings.Fields(gw.Bridges[msg.Account].GetString("IgnoreNicks")) {
|
||||||
if msg.Username == entry {
|
if msg.Username == entry {
|
||||||
log.Debugf("ignoring %s from %s", msg.Username, msg.Account)
|
flog.Debugf("ignoring %s from %s", msg.Username, msg.Account)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// does the message match regex in IgnoreMessages field
|
||||||
// TODO do not compile regexps everytime
|
// TODO do not compile regexps everytime
|
||||||
for _, entry := range strings.Fields(gw.Bridges[msg.Account].Config.IgnoreMessages) {
|
for _, entry := range strings.Fields(gw.Bridges[msg.Account].GetString("IgnoreMessages")) {
|
||||||
if entry != "" {
|
if entry != "" {
|
||||||
re, err := regexp.Compile(entry)
|
re, err := regexp.Compile(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("incorrect regexp %s for %s", entry, msg.Account)
|
flog.Errorf("incorrect regexp %s for %s", entry, msg.Account)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if re.MatchString(msg.Text) {
|
if re.MatchString(msg.Text) {
|
||||||
log.Debugf("matching %s. ignoring %s from %s", entry, msg.Text, msg.Account)
|
flog.Debugf("matching %s. ignoring %s from %s", entry, msg.Text, msg.Account)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,23 +337,23 @@ func (gw *Gateway) ignoreMessage(msg *config.Message) bool {
|
|||||||
func (gw *Gateway) modifyUsername(msg config.Message, dest *bridge.Bridge) string {
|
func (gw *Gateway) modifyUsername(msg config.Message, dest *bridge.Bridge) string {
|
||||||
br := gw.Bridges[msg.Account]
|
br := gw.Bridges[msg.Account]
|
||||||
msg.Protocol = br.Protocol
|
msg.Protocol = br.Protocol
|
||||||
if gw.Config.General.StripNick || dest.Config.StripNick {
|
if gw.Config.General.StripNick || dest.GetBool("StripNick") {
|
||||||
re := regexp.MustCompile("[^a-zA-Z0-9]+")
|
re := regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||||
msg.Username = re.ReplaceAllString(msg.Username, "")
|
msg.Username = re.ReplaceAllString(msg.Username, "")
|
||||||
}
|
}
|
||||||
nick := dest.Config.RemoteNickFormat
|
nick := dest.GetString("RemoteNickFormat")
|
||||||
if nick == "" {
|
if nick == "" {
|
||||||
nick = gw.Config.General.RemoteNickFormat
|
nick = gw.Config.General.RemoteNickFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop to replace nicks
|
// loop to replace nicks
|
||||||
for _, outer := range br.Config.ReplaceNicks {
|
for _, outer := range br.GetStringSlice2D("ReplaceNicks") {
|
||||||
search := outer[0]
|
search := outer[0]
|
||||||
replace := outer[1]
|
replace := outer[1]
|
||||||
// TODO move compile to bridge init somewhere
|
// TODO move compile to bridge init somewhere
|
||||||
re, err := regexp.Compile(search)
|
re, err := regexp.Compile(search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("regexp in %s failed: %s", msg.Account, err)
|
flog.Errorf("regexp in %s failed: %s", msg.Account, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
msg.Username = re.ReplaceAllString(msg.Username, replace)
|
msg.Username = re.ReplaceAllString(msg.Username, replace)
|
||||||
@@ -284,16 +371,18 @@ func (gw *Gateway) modifyUsername(msg config.Message, dest *bridge.Bridge) strin
|
|||||||
}
|
}
|
||||||
nick = strings.Replace(nick, "{NOPINGNICK}", msg.Username[:i]+""+msg.Username[i:], -1)
|
nick = strings.Replace(nick, "{NOPINGNICK}", msg.Username[:i]+""+msg.Username[i:], -1)
|
||||||
}
|
}
|
||||||
nick = strings.Replace(nick, "{NICK}", msg.Username, -1)
|
|
||||||
nick = strings.Replace(nick, "{BRIDGE}", br.Name, -1)
|
nick = strings.Replace(nick, "{BRIDGE}", br.Name, -1)
|
||||||
nick = strings.Replace(nick, "{PROTOCOL}", br.Protocol, -1)
|
nick = strings.Replace(nick, "{PROTOCOL}", br.Protocol, -1)
|
||||||
|
nick = strings.Replace(nick, "{LABEL}", br.GetString("Label"), -1)
|
||||||
|
nick = strings.Replace(nick, "{NICK}", msg.Username, -1)
|
||||||
return nick
|
return nick
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) modifyAvatar(msg config.Message, dest *bridge.Bridge) string {
|
func (gw *Gateway) modifyAvatar(msg config.Message, dest *bridge.Bridge) string {
|
||||||
iconurl := gw.Config.General.IconURL
|
iconurl := gw.Config.General.IconURL
|
||||||
if iconurl == "" {
|
if iconurl == "" {
|
||||||
iconurl = dest.Config.IconURL
|
iconurl = dest.GetString("IconURL")
|
||||||
}
|
}
|
||||||
iconurl = strings.Replace(iconurl, "{NICK}", msg.Username, -1)
|
iconurl = strings.Replace(iconurl, "{NICK}", msg.Username, -1)
|
||||||
if msg.Avatar == "" {
|
if msg.Avatar == "" {
|
||||||
@@ -305,58 +394,115 @@ func (gw *Gateway) modifyAvatar(msg config.Message, dest *bridge.Bridge) string
|
|||||||
func (gw *Gateway) modifyMessage(msg *config.Message) {
|
func (gw *Gateway) modifyMessage(msg *config.Message) {
|
||||||
// replace :emoji: to unicode
|
// replace :emoji: to unicode
|
||||||
msg.Text = emojilib.Replace(msg.Text)
|
msg.Text = emojilib.Replace(msg.Text)
|
||||||
|
|
||||||
br := gw.Bridges[msg.Account]
|
br := gw.Bridges[msg.Account]
|
||||||
// loop to replace messages
|
// loop to replace messages
|
||||||
for _, outer := range br.Config.ReplaceMessages {
|
for _, outer := range br.GetStringSlice2D("ReplaceMessages") {
|
||||||
search := outer[0]
|
search := outer[0]
|
||||||
replace := outer[1]
|
replace := outer[1]
|
||||||
// TODO move compile to bridge init somewhere
|
// TODO move compile to bridge init somewhere
|
||||||
re, err := regexp.Compile(search)
|
re, err := regexp.Compile(search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("regexp in %s failed: %s", msg.Account, err)
|
flog.Errorf("regexp in %s failed: %s", msg.Account, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
msg.Text = re.ReplaceAllString(msg.Text, replace)
|
msg.Text = re.ReplaceAllString(msg.Text, replace)
|
||||||
}
|
}
|
||||||
msg.Gateway = gw.Name
|
|
||||||
|
// messages from api have Gateway specified, don't overwrite
|
||||||
|
if msg.Protocol != "api" {
|
||||||
|
msg.Gateway = gw.Name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleFiles uploads or places all files on the given msg to the MediaServer and
|
||||||
|
// adds the new URL of the file on the MediaServer onto the given msg.
|
||||||
func (gw *Gateway) handleFiles(msg *config.Message) {
|
func (gw *Gateway) handleFiles(msg *config.Message) {
|
||||||
if msg.Extra == nil || gw.Config.General.MediaServerUpload == "" {
|
reg := regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||||
|
|
||||||
|
// If we don't have a attachfield or we don't have a mediaserver configured return
|
||||||
|
if msg.Extra == nil || (gw.Config.General.MediaServerUpload == "" && gw.Config.General.MediaDownloadPath == "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(msg.Extra["file"]) > 0 {
|
|
||||||
client := &http.Client{
|
|
||||||
Timeout: time.Second * 5,
|
|
||||||
}
|
|
||||||
for i, f := range msg.Extra["file"] {
|
|
||||||
fi := f.(config.FileInfo)
|
|
||||||
sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))
|
|
||||||
reader := bytes.NewReader(*fi.Data)
|
|
||||||
url := gw.Config.General.MediaServerUpload + "/" + sha1sum + "/" + fi.Name
|
|
||||||
durl := gw.Config.General.MediaServerDownload + "/" + sha1sum + "/" + fi.Name
|
|
||||||
extra := msg.Extra["file"][i].(config.FileInfo)
|
|
||||||
extra.URL = durl
|
|
||||||
msg.Extra["file"][i] = extra
|
|
||||||
req, _ := http.NewRequest("PUT", url, reader)
|
|
||||||
req.Header.Set("Content-Type", "binary/octet-stream")
|
|
||||||
_, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("mediaserver upload failed: %#v", err)
|
|
||||||
}
|
|
||||||
log.Debugf("mediaserver download URL = %s", durl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getChannelID(msg config.Message) string {
|
// If we don't have files, nothing to upload.
|
||||||
return msg.Channel + msg.Account
|
if len(msg.Extra["file"]) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
ext := filepath.Ext(fi.Name)
|
||||||
|
fi.Name = fi.Name[0 : len(fi.Name)-len(ext)]
|
||||||
|
fi.Name = reg.ReplaceAllString(fi.Name, "_")
|
||||||
|
fi.Name = fi.Name + ext
|
||||||
|
|
||||||
|
sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8]
|
||||||
|
|
||||||
|
if gw.Config.General.MediaServerUpload != "" {
|
||||||
|
// Use MediaServerUpload. Upload using a PUT HTTP request and basicauth.
|
||||||
|
|
||||||
|
url := gw.Config.General.MediaServerUpload + "/" + sha1sum + "/" + fi.Name
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", url, bytes.NewReader(*fi.Data))
|
||||||
|
if err != nil {
|
||||||
|
flog.Errorf("mediaserver upload failed, could not create request: %#v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
flog.Debugf("mediaserver upload url: %s", url)
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "binary/octet-stream")
|
||||||
|
_, err = client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
flog.Errorf("mediaserver upload failed, could not Do request: %#v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Use MediaServerPath. Place the file on the current filesystem.
|
||||||
|
|
||||||
|
dir := gw.Config.General.MediaDownloadPath + "/" + sha1sum
|
||||||
|
err := os.Mkdir(dir, os.ModePerm)
|
||||||
|
if err != nil && !os.IsExist(err) {
|
||||||
|
flog.Errorf("mediaserver path failed, could not mkdir: %s %#v", err, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
path := dir + "/" + fi.Name
|
||||||
|
flog.Debugf("mediaserver path placing file: %s", path)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(path, *fi.Data, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
flog.Errorf("mediaserver path failed, could not writefile: %s %#v", err, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download URL.
|
||||||
|
durl := gw.Config.General.MediaServerDownload + "/" + sha1sum + "/" + fi.Name
|
||||||
|
|
||||||
|
flog.Debugf("mediaserver download URL = %s", durl)
|
||||||
|
|
||||||
|
// We uploaded/placed the file successfully. Add the SHA and URL.
|
||||||
|
extra := msg.Extra["file"][i].(config.FileInfo)
|
||||||
|
extra.URL = durl
|
||||||
|
extra.SHA = sha1sum
|
||||||
|
msg.Extra["file"][i] = extra
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *Gateway) validGatewayDest(msg *config.Message, channel *config.ChannelInfo) bool {
|
func (gw *Gateway) validGatewayDest(msg *config.Message, channel *config.ChannelInfo) bool {
|
||||||
return msg.Gateway == gw.Name
|
return msg.Gateway == gw.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getChannelID(msg config.Message) string {
|
||||||
|
return msg.Channel + msg.Account
|
||||||
|
}
|
||||||
|
|
||||||
func isApi(account string) bool {
|
func isApi(account string) bool {
|
||||||
return strings.HasPrefix(account, "api.")
|
return strings.HasPrefix(account, "api.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ package gateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testconfig = `
|
var testconfig = []byte(`
|
||||||
[irc.freenode]
|
[irc.freenode]
|
||||||
[mattermost.test]
|
[mattermost.test]
|
||||||
[gitter.42wim]
|
[gitter.42wim]
|
||||||
@@ -37,9 +37,9 @@ var testconfig = `
|
|||||||
[[gateway.inout]]
|
[[gateway.inout]]
|
||||||
account="slack.test"
|
account="slack.test"
|
||||||
channel="testing"
|
channel="testing"
|
||||||
`
|
`)
|
||||||
|
|
||||||
var testconfig2 = `
|
var testconfig2 = []byte(`
|
||||||
[irc.freenode]
|
[irc.freenode]
|
||||||
[mattermost.test]
|
[mattermost.test]
|
||||||
[gitter.42wim]
|
[gitter.42wim]
|
||||||
@@ -80,8 +80,9 @@ var testconfig2 = `
|
|||||||
[[gateway.out]]
|
[[gateway.out]]
|
||||||
account = "discord.test"
|
account = "discord.test"
|
||||||
channel = "general2"
|
channel = "general2"
|
||||||
`
|
`)
|
||||||
var testconfig3 = `
|
|
||||||
|
var testconfig3 = []byte(`
|
||||||
[irc.zzz]
|
[irc.zzz]
|
||||||
[telegram.zzz]
|
[telegram.zzz]
|
||||||
[slack.zzz]
|
[slack.zzz]
|
||||||
@@ -149,13 +150,10 @@ enable=true
|
|||||||
[[gateway.inout]]
|
[[gateway.inout]]
|
||||||
account="telegram.zzz"
|
account="telegram.zzz"
|
||||||
channel="--333333333333"
|
channel="--333333333333"
|
||||||
`
|
`)
|
||||||
|
|
||||||
func maketestRouter(input string) *Router {
|
func maketestRouter(input []byte) *Router {
|
||||||
var cfg *config.Config
|
cfg := config.NewConfigFromString(input)
|
||||||
if _, err := toml.Decode(input, &cfg); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
r, err := NewRouter(cfg)
|
r, err := NewRouter(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -163,14 +161,7 @@ func maketestRouter(input string) *Router {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
func TestNewRouter(t *testing.T) {
|
func TestNewRouter(t *testing.T) {
|
||||||
var cfg *config.Config
|
r := maketestRouter(testconfig)
|
||||||
if _, err := toml.Decode(testconfig, &cfg); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
r, err := NewRouter(cfg)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
assert.Equal(t, 1, len(r.Gateways))
|
assert.Equal(t, 1, len(r.Gateways))
|
||||||
assert.Equal(t, 4, len(r.Gateways["bridge1"].Bridges))
|
assert.Equal(t, 4, len(r.Gateways["bridge1"].Bridges))
|
||||||
assert.Equal(t, 4, len(r.Gateways["bridge1"].Channels))
|
assert.Equal(t, 4, len(r.Gateways["bridge1"].Channels))
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package gateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/gateway/samechannel"
|
samechannelgateway "github.com/42wim/matterbridge/gateway/samechannel"
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -17,10 +17,7 @@ type Router struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter(cfg *config.Config) (*Router, error) {
|
func NewRouter(cfg *config.Config) (*Router, error) {
|
||||||
r := &Router{}
|
r := &Router{Message: make(chan config.Message), Gateways: make(map[string]*Gateway), Config: cfg}
|
||||||
r.Config = cfg
|
|
||||||
r.Message = make(chan config.Message)
|
|
||||||
r.Gateways = make(map[string]*Gateway)
|
|
||||||
sgw := samechannelgateway.New(cfg)
|
sgw := samechannelgateway.New(cfg)
|
||||||
gwconfigs := sgw.GetConfig()
|
gwconfigs := sgw.GetConfig()
|
||||||
|
|
||||||
@@ -42,12 +39,13 @@ func NewRouter(cfg *config.Config) (*Router, error) {
|
|||||||
func (r *Router) Start() error {
|
func (r *Router) Start() error {
|
||||||
m := make(map[string]*bridge.Bridge)
|
m := make(map[string]*bridge.Bridge)
|
||||||
for _, gw := range r.Gateways {
|
for _, gw := range r.Gateways {
|
||||||
|
flog.Infof("Parsing gateway %s", gw.Name)
|
||||||
for _, br := range gw.Bridges {
|
for _, br := range gw.Bridges {
|
||||||
m[br.Account] = br
|
m[br.Account] = br
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, br := range m {
|
for _, br := range m {
|
||||||
log.Infof("Starting bridge: %s ", br.Account)
|
flog.Infof("Starting bridge: %s ", br.Account)
|
||||||
err := br.Connect()
|
err := br.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Bridge %s failed to start: %v", br.Account, err)
|
return fmt.Errorf("Bridge %s failed to start: %v", br.Account, err)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package samechannelgateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|||||||
83
go.mod
Normal file
83
go.mod
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
module github.com/42wim/matterbridge
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557
|
||||||
|
github.com/BurntSushi/toml v0.0.0-20170318202913-d94612f9fc14
|
||||||
|
github.com/Philipp15b/go-steam v0.0.0-20161020161927-e0f3bb9566e3
|
||||||
|
github.com/Sirupsen/logrus v1.0.6 // indirect
|
||||||
|
github.com/alecthomas/log4go v0.0.0-20160307011253-e5dc62318d9b // indirect
|
||||||
|
github.com/bwmarrin/discordgo v0.0.0-20180201002541-8d5ab59c63e5 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
|
github.com/dfordsoft/golib v0.0.0-20180313113957-2ea3495aee1d
|
||||||
|
github.com/dgrijalva/jwt-go v0.0.0-20170508165458-6c8dedd55f8a // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7
|
||||||
|
github.com/go-telegram-bot-api/telegram-bot-api v0.0.0-20180428185002-212b1541150c
|
||||||
|
github.com/golang/protobuf v0.0.0-20170613224224-e325f446bebc // indirect
|
||||||
|
github.com/google/gops v0.0.0-20170319002943-62f833fc9f6c
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f // indirect
|
||||||
|
github.com/gorilla/schema v0.0.0-20170317173100-f3c80893412c
|
||||||
|
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777
|
||||||
|
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad
|
||||||
|
github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb // indirect
|
||||||
|
github.com/hpcloud/tail v1.0.0 // indirect
|
||||||
|
github.com/jpillora/backoff v0.0.0-20170222002228-06c7a16c845d
|
||||||
|
github.com/jtolds/gls v4.2.1+incompatible // indirect
|
||||||
|
github.com/kardianos/osext v0.0.0-20170207191655-9b883c5eb462 // indirect
|
||||||
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
|
github.com/labstack/echo v0.0.0-20180219162101-7eec915044a1
|
||||||
|
github.com/labstack/gommon v0.2.1 // indirect
|
||||||
|
github.com/lrstanley/girc v0.0.0-20180427160007-102f17f86306
|
||||||
|
github.com/magiconair/properties v0.0.0-20180217134545-2c9e95027885 // indirect
|
||||||
|
github.com/matterbridge/discordgo v0.0.0-20180806170629-ef40ff5ba64f
|
||||||
|
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91
|
||||||
|
github.com/matterbridge/gomatrix v0.0.0-20171224233421-78ac6a1a0f5f
|
||||||
|
github.com/matterbridge/gozulipbot v0.0.0-20180507190239-b6bb12d33544
|
||||||
|
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61
|
||||||
|
github.com/mattermost/platform v4.6.2+incompatible
|
||||||
|
github.com/mattn/go-colorable v0.0.0-20170210172801-5411d3eea597 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.0-20170216235908-dda3de49cbfc // indirect
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 // indirect
|
||||||
|
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 // indirect
|
||||||
|
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect
|
||||||
|
github.com/nicksnyder/go-i18n v1.4.0 // indirect
|
||||||
|
github.com/nlopes/slack v0.3.1-0.20180805133408-21749ab136a8
|
||||||
|
github.com/onsi/ginkgo v1.6.0 // indirect
|
||||||
|
github.com/onsi/gomega v1.4.1 // indirect
|
||||||
|
github.com/paulrosania/go-charset v0.0.0-20151028000031-621bb39fcc83
|
||||||
|
github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 // indirect
|
||||||
|
github.com/pelletier/go-toml v0.0.0-20180228233631-05bcc0fb0d3e // indirect
|
||||||
|
github.com/peterhellberg/emojilib v0.0.0-20170616163716-41920917e271
|
||||||
|
github.com/pkg/errors v0.8.0 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/rs/xid v0.0.0-20180525034800-088c5cf1423a
|
||||||
|
github.com/russross/blackfriday v1.5.1
|
||||||
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||||
|
github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1 // indirect
|
||||||
|
github.com/shazow/ssh-chat v0.0.0-20171012174035-2078e1381991
|
||||||
|
github.com/sirupsen/logrus v0.0.0-20180213143110-8c0189d9f6bb
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9 // indirect
|
||||||
|
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect
|
||||||
|
github.com/spf13/afero v0.0.0-20180211162714-bbf41cb36dff // indirect
|
||||||
|
github.com/spf13/cast v1.2.0 // indirect
|
||||||
|
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec // indirect
|
||||||
|
github.com/spf13/pflag v0.0.0-20180220143236-ee5fd03fd6ac // indirect
|
||||||
|
github.com/spf13/viper v0.0.0-20171227194143-aafc9e6bc7b7
|
||||||
|
github.com/stretchr/testify v0.0.0-20170714215325-05e8a0eda380
|
||||||
|
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||||
|
github.com/valyala/bytebufferpool v0.0.0-20160817181652-e746df99fe4a // indirect
|
||||||
|
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect
|
||||||
|
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
|
||||||
|
github.com/zfjagann/golang-ring v0.0.0-20141111230621-17637388c9f6
|
||||||
|
golang.org/x/crypto v0.0.0-20180228161326-91a49db82a88 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20180108090419-434ec0c7fe37 // indirect
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20171130163741-8b4580aae2a0 // indirect
|
||||||
|
golang.org/x/text v0.0.0-20180511172408-5c1cf69b5978 // indirect
|
||||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
||||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.1 // indirect
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20160301204022-a83829b6f129 // indirect
|
||||||
|
)
|
||||||
163
go.sum
Normal file
163
go.sum
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557 h1:IZtuWGfzQnKnCSu+vl8WGLhpVQ5Uvy3rlSwqXSg+sQg=
|
||||||
|
github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557/go.mod h1:jL0YSXMs/txjtGJ4PWrmETOk6KUHMDPMshgQZlTeB3Y=
|
||||||
|
github.com/BurntSushi/toml v0.0.0-20170318202913-d94612f9fc14 h1:v/zr4ns/4sSahF9KBm4Uc933bLsEEv7LuT63CJ019yo=
|
||||||
|
github.com/BurntSushi/toml v0.0.0-20170318202913-d94612f9fc14/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Philipp15b/go-steam v0.0.0-20161020161927-e0f3bb9566e3 h1:V4+1E1SRYUySqwOoI3ZphFADtabbF568zTHa5ix/zU0=
|
||||||
|
github.com/Philipp15b/go-steam v0.0.0-20161020161927-e0f3bb9566e3/go.mod h1:HuVM+sZFzumUdKPWiz+IlCMb4RdsKdT3T+nQBKL+sYg=
|
||||||
|
github.com/Sirupsen/logrus v1.0.6 h1:HCAGQRk48dRVPA5Y+Yh0qdCSTzPOyU1tBJ7Q9YzotII=
|
||||||
|
github.com/Sirupsen/logrus v1.0.6/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U=
|
||||||
|
github.com/alecthomas/log4go v0.0.0-20160307011253-e5dc62318d9b h1:1OpGXps6UOY5HtQaQcLowsV1qMWCNBzhFvK7q4fgXtc=
|
||||||
|
github.com/alecthomas/log4go v0.0.0-20160307011253-e5dc62318d9b/go.mod h1:iCVmQ9g4TfaRX5m5jq5sXY7RXYWPv9/PynM/GocbG3w=
|
||||||
|
github.com/bwmarrin/discordgo v0.0.0-20180201002541-8d5ab59c63e5 h1:M7u44DKGpA5goDIBf0zRMYhT1Sp2Rd7hiTzXfeuw1UY=
|
||||||
|
github.com/bwmarrin/discordgo v0.0.0-20180201002541-8d5ab59c63e5/go.mod h1:5NIvFv5Z7HddYuXbuQegZ684DleQaCFqChP2iuBivJ8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dfordsoft/golib v0.0.0-20180313113957-2ea3495aee1d h1:rONNnZDE5CYuaSFQk+gP4GEQTXEUcyQ5p6p/dgxIHas=
|
||||||
|
github.com/dfordsoft/golib v0.0.0-20180313113957-2ea3495aee1d/go.mod h1:UGa5M2Sz/Uh13AMse4+RELKCDw7kqgqlTjeGae+7vUY=
|
||||||
|
github.com/dgrijalva/jwt-go v0.0.0-20170508165458-6c8dedd55f8a h1:MuHMeSsXbNEeUyxjB7T9P8s1+5k8OLTC/M27qsVwixM=
|
||||||
|
github.com/dgrijalva/jwt-go v0.0.0-20170508165458-6c8dedd55f8a/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/go-telegram-bot-api/telegram-bot-api v0.0.0-20180428185002-212b1541150c h1:3gMh737vMGqAkkkSfNbwjO8VRHOSaCjYRG4y9xVMEIQ=
|
||||||
|
github.com/go-telegram-bot-api/telegram-bot-api v0.0.0-20180428185002-212b1541150c/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
||||||
|
github.com/golang/protobuf v0.0.0-20170613224224-e325f446bebc h1:wdhDSKrkYy24mcfzuA3oYm58h0QkyXjwERCkzJDP5kA=
|
||||||
|
github.com/golang/protobuf v0.0.0-20170613224224-e325f446bebc/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/gops v0.0.0-20170319002943-62f833fc9f6c h1:MrMA1vhRTNidtgENqmsmLOIUS6ixMBOU/g10rm7IUe8=
|
||||||
|
github.com/google/gops v0.0.0-20170319002943-62f833fc9f6c/go.mod h1:pMQgrscwEK/aUSW1IFSaBPbJX82FPHWaSoJw1axQfD0=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f h1:FDM3EtwZLyhW48YRiyqjivNlNZjAObv4xt4NnJaU+NQ=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gorilla/schema v0.0.0-20170317173100-f3c80893412c h1:mORYpib1aLu3M2Oi50Z1pNTXuDJEHcoLb6oo6VdOutk=
|
||||||
|
github.com/gorilla/schema v0.0.0-20170317173100-f3c80893412c/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||||
|
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777 h1:JIM+OacoOJRU30xpjMf8sulYqjr0ViA3WDrTX6j/yDI=
|
||||||
|
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad h1:eMxs9EL0PvIGS9TTtxg4R+JxuPGav82J8rA+GFnY7po=
|
||||||
|
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb h1:1OvvPvZkn/yCQ3xBcM8y4020wdkMXPHLB4+NfoGWh4U=
|
||||||
|
github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||||
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/jpillora/backoff v0.0.0-20170222002228-06c7a16c845d h1:ETeT81zgLgSNc4BWdDO2Fg9ekVItYErbNtE8mKD2pJA=
|
||||||
|
github.com/jpillora/backoff v0.0.0-20170222002228-06c7a16c845d/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
||||||
|
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
|
||||||
|
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/kardianos/osext v0.0.0-20170207191655-9b883c5eb462 h1:oSOOTPHkCzMeu1vJ0nHxg5+XZBdMMjNa+6NPnm8arok=
|
||||||
|
github.com/kardianos/osext v0.0.0-20170207191655-9b883c5eb462/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/labstack/echo v0.0.0-20180219162101-7eec915044a1 h1:cOIt0LZKdfeirAfTP4VtIJuWbjVTGtd1suuPXp/J+dE=
|
||||||
|
github.com/labstack/echo v0.0.0-20180219162101-7eec915044a1/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
|
||||||
|
github.com/labstack/gommon v0.2.1 h1:C+I4NYknueQncqKYZQ34kHsLZJVeB5KwPUhnO0nmbpU=
|
||||||
|
github.com/labstack/gommon v0.2.1/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
|
||||||
|
github.com/lrstanley/girc v0.0.0-20180427160007-102f17f86306 h1:IqN61cmi7LM/IaYaP9a/KXFtHRS2a3+WHu8GhAXJT7c=
|
||||||
|
github.com/lrstanley/girc v0.0.0-20180427160007-102f17f86306/go.mod h1:7cRs1SIBfKQ7e3Tam6GKTILSNHzR862JD0JpINaZoJk=
|
||||||
|
github.com/magiconair/properties v0.0.0-20180217134545-2c9e95027885 h1:HWxJJvF+QceKcql4r9PC93NtMEgEBfBxlQrZPvbcQvs=
|
||||||
|
github.com/magiconair/properties v0.0.0-20180217134545-2c9e95027885/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/matterbridge/discordgo v0.0.0-20180806170629-ef40ff5ba64f h1:9IIOO9Aznn8zJx3nokZ4U6nfuzWw5xAlygPvuRZMisQ=
|
||||||
|
github.com/matterbridge/discordgo v0.0.0-20180806170629-ef40ff5ba64f/go.mod h1:5QtN542bJn9FunZqYlIbleNtToxfLCVV9pW7m7Q42Fc=
|
||||||
|
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 h1:KzDEcy8eDbTx881giW8a6llsAck3e2bJvMyKvh1IK+k=
|
||||||
|
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
||||||
|
github.com/matterbridge/gomatrix v0.0.0-20171224233421-78ac6a1a0f5f h1:2eKh6Qi/sJ8bXvYMoyVfQxHgR8UcCDWjOmhV1oCstMU=
|
||||||
|
github.com/matterbridge/gomatrix v0.0.0-20171224233421-78ac6a1a0f5f/go.mod h1:+jWeaaUtXQbBRdKYWfjW6JDDYiI2XXE+3NnTjW5kg8g=
|
||||||
|
github.com/matterbridge/gozulipbot v0.0.0-20180507190239-b6bb12d33544 h1:A8lLG3DAu75B5jITHs9z4JBmU6oCq1WiUNnDAmqKCZc=
|
||||||
|
github.com/matterbridge/gozulipbot v0.0.0-20180507190239-b6bb12d33544/go.mod h1:yAjnZ34DuDyPHMPHHjOsTk/FefW4JJjoMMCGt/8uuQA=
|
||||||
|
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61 h1:R/MgM/eUyRBQx2FiH6JVmXck8PaAuKfe2M1tWIzW7nE=
|
||||||
|
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61/go.mod h1:iXGEotOvwI1R1SjLxRc+BF5rUORTMtE0iMZBT2lxqAU=
|
||||||
|
github.com/mattermost/platform v4.6.2+incompatible h1:9WqKNuJFIp6SDYn5wl1RF5urdhEw8d7o5tAOwT1MW0A=
|
||||||
|
github.com/mattermost/platform v4.6.2+incompatible/go.mod h1:HjGKtkQNu3HXTOykPMQckMnH11WHvNvQqDBNnVXVbfM=
|
||||||
|
github.com/mattn/go-colorable v0.0.0-20170210172801-5411d3eea597 h1:hGizH4aMDFFt1iOA4HNKC13lqIBoCyxIjWcAnWIy7aU=
|
||||||
|
github.com/mattn/go-colorable v0.0.0-20170210172801-5411d3eea597/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-isatty v0.0.0-20170216235908-dda3de49cbfc h1:pK7tzC30erKOTfEDCYGvPZQCkmM9X5iSmmAR5m9x3Yc=
|
||||||
|
github.com/mattn/go-isatty v0.0.0-20170216235908-dda3de49cbfc/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 h1:+MZW2uvHgN8kYvksEN3f7eFL2wpzk0GxmlFsMybWc7E=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 h1:oKIteTqeSpenyTrOVj5zkiyCaflLa8B+CD0324otT+o=
|
||||||
|
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||||
|
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff h1:HLGD5/9UxxfEuO9DtP8gnTmNtMxbPyhYltfxsITel8g=
|
||||||
|
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff/go.mod h1:B8jLfIIPn2sKyWr0D7cL2v7tnrDD5z291s2Zypdu89E=
|
||||||
|
github.com/nicksnyder/go-i18n v1.4.0 h1:AgLl+Yq7kg5OYlzCgu9cKTZOyI4tD/NgukKqLqC8E+I=
|
||||||
|
github.com/nicksnyder/go-i18n v1.4.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
|
||||||
|
github.com/nlopes/slack v0.0.0-20180101221843-107290b5bbaf h1:M+xGhDxie/MqC+tzs+3ZHBSY4Wsv+fEkrpIMCKy8PTg=
|
||||||
|
github.com/nlopes/slack v0.0.0-20180101221843-107290b5bbaf/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
|
||||||
|
github.com/nlopes/slack v0.3.1-0.20180805133408-21749ab136a8 h1:PSy8NkmkyldLmPPnNNw7mwfQFOHDqOI6bINpJ+/KV7Y=
|
||||||
|
github.com/nlopes/slack v0.3.1-0.20180805133408-21749ab136a8/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
|
||||||
|
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U=
|
||||||
|
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
|
github.com/paulrosania/go-charset v0.0.0-20151028000031-621bb39fcc83 h1:XQonH5Iv5rbyIkMJOQ4xKmKHQTh8viXtRSmep5Ca5I4=
|
||||||
|
github.com/paulrosania/go-charset v0.0.0-20151028000031-621bb39fcc83/go.mod h1:YnNlZP7l4MhyGQ4CBRwv6ohZTPrUJJZtEv4ZgADkbs4=
|
||||||
|
github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 h1:/CPgDYrfeK2LMK6xcUhvI17yO9SlpAdDIJGkhDEgO8A=
|
||||||
|
github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
||||||
|
github.com/pelletier/go-toml v0.0.0-20180228233631-05bcc0fb0d3e h1:ZW8599OjioQsmBbkGpyruHUlRVQceYFWnJsGr4NCkiA=
|
||||||
|
github.com/pelletier/go-toml v0.0.0-20180228233631-05bcc0fb0d3e/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/peterhellberg/emojilib v0.0.0-20170616163716-41920917e271 h1:wQ9lVx75za6AT2kI0S9QID0uWuwTWnvcTfN+uw1F8vg=
|
||||||
|
github.com/peterhellberg/emojilib v0.0.0-20170616163716-41920917e271/go.mod h1:G7LufuPajuIvdt9OitkNt2qh0mmvD4bfRgRM7bhDIOA=
|
||||||
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rs/xid v0.0.0-20180525034800-088c5cf1423a h1:UWKek6MK3K6/TpbsFcv+8rrO6rSc6KKSp2FbMOHWsq4=
|
||||||
|
github.com/rs/xid v0.0.0-20180525034800-088c5cf1423a/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||||
|
github.com/russross/blackfriday v1.5.1 h1:B8ZN6pD4PVofmlDCDUdELeYrbsVIDM/bpjW3v3zgcRc=
|
||||||
|
github.com/russross/blackfriday v1.5.1/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
|
||||||
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||||
|
github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1 h1:Lx3BlDGFElJt4u/zKc9A3BuGYbQAGlEFyPuUA3jeMD0=
|
||||||
|
github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI=
|
||||||
|
github.com/shazow/ssh-chat v0.0.0-20171012174035-2078e1381991 h1:PQiUTDzUC5EUh0vNurK7KQS22zlKqLLOFn+K9nJXDQQ=
|
||||||
|
github.com/shazow/ssh-chat v0.0.0-20171012174035-2078e1381991/go.mod h1:KwtnpMClmrXsHCKTbRui5xBUNt17n1GGrGhdiw2KcoY=
|
||||||
|
github.com/sirupsen/logrus v0.0.0-20180213143110-8c0189d9f6bb h1:eKjx20EiekBRT2tjZ0XEdKpftfPJQwiavtFshwTyqf0=
|
||||||
|
github.com/sirupsen/logrus v0.0.0-20180213143110-8c0189d9f6bb/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9 h1:lXQ+j+KwZcbwrbgU0Rp4Eglg3EJLHbuZU3BbOqAGBmg=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo=
|
||||||
|
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||||
|
github.com/spf13/afero v0.0.0-20180211162714-bbf41cb36dff h1:HLvGWId7M56TfuxTeZ6aoiTAcrWO5Mnq/ArwVRgV62I=
|
||||||
|
github.com/spf13/afero v0.0.0-20180211162714-bbf41cb36dff/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg=
|
||||||
|
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||||
|
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec h1:2ZXvIUGghLpdTVHR1UfvfrzoVlZaE/yOWC5LueIHZig=
|
||||||
|
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v0.0.0-20180220143236-ee5fd03fd6ac h1:+uzyQ0TQ3aKorQxsOjcDDgE7CuUXwpkKnK19LULQALQ=
|
||||||
|
github.com/spf13/pflag v0.0.0-20180220143236-ee5fd03fd6ac/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/viper v0.0.0-20171227194143-aafc9e6bc7b7 h1:Wj4cg2M6Um7j1N7yD/mxsdy1/wrsdjzVha2eWdOhti8=
|
||||||
|
github.com/spf13/viper v0.0.0-20171227194143-aafc9e6bc7b7/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||||
|
github.com/stretchr/testify v0.0.0-20170714215325-05e8a0eda380 h1:MsolbevHkd4SpbeG4dHLHj6I9jzoohyNI6EK6JvR5hE=
|
||||||
|
github.com/stretchr/testify v0.0.0-20170714215325-05e8a0eda380/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||||
|
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||||
|
github.com/valyala/bytebufferpool v0.0.0-20160817181652-e746df99fe4a h1:AOcehBWpFhYPYw0ioDTppQzgI8pAAahVCiMSKTp9rbo=
|
||||||
|
github.com/valyala/bytebufferpool v0.0.0-20160817181652-e746df99fe4a/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8=
|
||||||
|
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
|
||||||
|
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
||||||
|
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||||
|
github.com/zfjagann/golang-ring v0.0.0-20141111230621-17637388c9f6 h1:/WULP+6asFz569UbOwg87f3iDT7T+GF5/vjLmL51Pdk=
|
||||||
|
github.com/zfjagann/golang-ring v0.0.0-20141111230621-17637388c9f6/go.mod h1:0MsIttMJIF/8Y7x0XjonJP7K99t3sR6bjj4m5S4JmqU=
|
||||||
|
golang.org/x/crypto v0.0.0-20180228161326-91a49db82a88 h1:jLkAo/qlT9whgCLYC5GAJ9kcKrv3Wj8VCc4N+KJ4wpw=
|
||||||
|
golang.org/x/crypto v0.0.0-20180228161326-91a49db82a88/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/net v0.0.0-20180108090419-434ec0c7fe37 h1:BkNcmLtAVeWe9h5k0jt24CQgaG5vb4x/doFbAiEC/Ho=
|
||||||
|
golang.org/x/net v0.0.0-20180108090419-434ec0c7fe37/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20171130163741-8b4580aae2a0 h1:x4M4WCms+ErQg/4VyECbP2kSNcDJ6nLwqEGov1QPtqk=
|
||||||
|
golang.org/x/sys v0.0.0-20171130163741-8b4580aae2a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.0.0-20180511172408-5c1cf69b5978 h1:WNm0tmiuBMW4FJRuXKWOqaQfmKptHs0n8nTCyG0ayjc=
|
||||||
|
golang.org/x/text v0.0.0-20180511172408-5c1cf69b5978/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
||||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.1 h1:4buh9nXkpqc7+GLzDFHei0jwoU9wCQYfVB5Kfo58Yz0=
|
||||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.1/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20160301204022-a83829b6f129 h1:RBgb9aPUbZ9nu66ecQNIBNsA7j3mB5h8PNDIfhPjaJg=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20160301204022-a83829b6f129/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
BIN
img/matterbridge.gif
Normal file
BIN
img/matterbridge.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
@@ -3,24 +3,24 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
|
||||||
"github.com/42wim/matterbridge/gateway"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/google/gops/agent"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/gateway"
|
||||||
|
"github.com/google/gops/agent"
|
||||||
|
prefixed "github.com/matterbridge/logrus-prefixed-formatter"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "1.6.0"
|
version = "1.11.3"
|
||||||
githash string
|
githash string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
log.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: true})
|
||||||
|
flog := log.WithFields(log.Fields{"prefix": "main"})
|
||||||
flagConfig := flag.String("conf", "matterbridge.toml", "config file")
|
flagConfig := flag.String("conf", "matterbridge.toml", "config file")
|
||||||
flagDebug := flag.Bool("debug", false, "enable debug")
|
flagDebug := flag.Bool("debug", false, "enable debug")
|
||||||
flagVersion := flag.Bool("version", false, "show version")
|
flagVersion := flag.Bool("version", false, "show version")
|
||||||
@@ -35,22 +35,24 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if *flagDebug || os.Getenv("DEBUG") == "1" {
|
if *flagDebug || os.Getenv("DEBUG") == "1" {
|
||||||
log.Info("Enabling debug")
|
log.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: false, ForceFormatting: true})
|
||||||
|
flog.Info("Enabling debug")
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
}
|
}
|
||||||
log.Printf("Running version %s %s", version, githash)
|
flog.Printf("Running version %s %s", version, githash)
|
||||||
if strings.Contains(version, "-dev") {
|
if strings.Contains(version, "-dev") {
|
||||||
log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
|
flog.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
|
||||||
}
|
}
|
||||||
cfg := config.NewConfig(*flagConfig)
|
cfg := config.NewConfig(*flagConfig)
|
||||||
|
cfg.General.Debug = *flagDebug
|
||||||
r, err := gateway.NewRouter(cfg)
|
r, err := gateway.NewRouter(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Starting gateway failed: %s", err)
|
flog.Fatalf("Starting gateway failed: %s", err)
|
||||||
}
|
}
|
||||||
err = r.Start()
|
err = r.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Starting gateway failed: %s", err)
|
flog.Fatalf("Starting gateway failed: %s", err)
|
||||||
}
|
}
|
||||||
log.Printf("Gateway(s) started succesfully. Now relaying messages")
|
flog.Printf("Gateway(s) started succesfully. Now relaying messages")
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ NickServPassword="secret"
|
|||||||
#OPTIONAL only used for quakenet auth
|
#OPTIONAL only used for quakenet auth
|
||||||
NickServUsername="username"
|
NickServUsername="username"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Flood control
|
#Flood control
|
||||||
#Delay in milliseconds between each message send to the IRC server
|
#Delay in milliseconds between each message send to the IRC server
|
||||||
#OPTIONAL (default 1300)
|
#OPTIONAL (default 1300)
|
||||||
@@ -89,6 +92,10 @@ MessageSplit=false
|
|||||||
#OPTIONAL (default 0)
|
#OPTIONAL (default 0)
|
||||||
RejoinDelay=0
|
RejoinDelay=0
|
||||||
|
|
||||||
|
#ColorNicks will show each nickname in a different color.
|
||||||
|
#Only works in IRC right now.
|
||||||
|
ColorNicks=false
|
||||||
|
|
||||||
#Nicks you want to ignore.
|
#Nicks you want to ignore.
|
||||||
#Messages from those users will not be sent to other bridges.
|
#Messages from those users will not be sent to other bridges.
|
||||||
#OPTIONAL
|
#OPTIONAL
|
||||||
@@ -117,24 +124,39 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#The string "{NOPINGNICK}" (case sensitive) will be replaced by the actual nick / username, but with a ZWSP inside the nick, so the irc user with the same nick won't get pinged. See https://github.com/42wim/matterbridge/issues/175 for more information
|
#The string "{NOPINGNICK}" (case sensitive) will be replaced by the actual nick / username, but with a ZWSP inside the nick, so the irc user with the same nick won't get pinged. See https://github.com/42wim/matterbridge/issues/175 for more information
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
|
#Do not send joins/parts to other bridges
|
||||||
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
NoSendJoinPart=false
|
||||||
|
|
||||||
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
||||||
#It will strip other characters from the nick
|
#It will strip other characters from the nick
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#XMPP section
|
#XMPP section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -169,6 +191,9 @@ Nick="xmppbot"
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
SkipTLSVerify=true
|
SkipTLSVerify=true
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Nicks you want to ignore.
|
#Nicks you want to ignore.
|
||||||
#Messages from those users will not be sent to other bridges.
|
#Messages from those users will not be sent to other bridges.
|
||||||
#OPTIONAL
|
#OPTIONAL
|
||||||
@@ -197,15 +222,20 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -214,6 +244,11 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#hipchat section
|
#hipchat section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -240,6 +275,9 @@ Muc="conf.hipchat.com"
|
|||||||
#REQUIRED
|
#REQUIRED
|
||||||
Nick="yourlogin"
|
Nick="yourlogin"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Nicks you want to ignore.
|
#Nicks you want to ignore.
|
||||||
#Messages from those users will not be sent to other bridges.
|
#Messages from those users will not be sent to other bridges.
|
||||||
#OPTIONAL
|
#OPTIONAL
|
||||||
@@ -268,15 +306,20 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}/{BRIDGE}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}/{BRIDGE}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -285,6 +328,11 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#mattermost section
|
#mattermost section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -347,6 +395,9 @@ IconURL="http://youricon.png"
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
SkipTLSVerify=true
|
SkipTLSVerify=true
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#how to format the list of IRC nicks when displayed in mattermost.
|
#how to format the list of IRC nicks when displayed in mattermost.
|
||||||
#Possible options are "table" and "plain"
|
#Possible options are "table" and "plain"
|
||||||
#OPTIONAL (default plain)
|
#OPTIONAL (default plain)
|
||||||
@@ -399,23 +450,38 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
|
#Do not send joins/parts to other bridges
|
||||||
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
NoSendJoinPart=false
|
||||||
|
|
||||||
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
||||||
#It will strip other characters from the nick
|
#It will strip other characters from the nick
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#Gitter section
|
#Gitter section
|
||||||
#Best to make a dedicated gitter account for the bot.
|
#Best to make a dedicated gitter account for the bot.
|
||||||
@@ -432,6 +498,9 @@ StripNick=false
|
|||||||
#REQUIRED
|
#REQUIRED
|
||||||
Token="Yourtokenhere"
|
Token="Yourtokenhere"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Nicks you want to ignore.
|
#Nicks you want to ignore.
|
||||||
#Messages from those users will not be sent to other bridges.
|
#Messages from those users will not be sent to other bridges.
|
||||||
#OPTIONAL
|
#OPTIONAL
|
||||||
@@ -460,15 +529,20 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -477,6 +551,11 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#slack section
|
#slack section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -512,10 +591,14 @@ WebhookBindAddress="0.0.0.0:9999"
|
|||||||
#Icon that will be showed in slack
|
#Icon that will be showed in slack
|
||||||
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL
|
#OPTIONAL
|
||||||
IconURL="https://robohash.org/{NICK}.png?size=48x48"
|
IconURL="https://robohash.org/{NICK}.png?size=48x48"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#how to format the list of IRC nicks when displayed in slack
|
#how to format the list of IRC nicks when displayed in slack
|
||||||
#Possible options are "table" and "plain"
|
#Possible options are "table" and "plain"
|
||||||
#OPTIONAL (default plain)
|
#OPTIONAL (default plain)
|
||||||
@@ -568,23 +651,38 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
|
#Do not send joins/parts to other bridges
|
||||||
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
NoSendJoinPart=false
|
||||||
|
|
||||||
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
||||||
#It will strip other characters from the nick
|
#It will strip other characters from the nick
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#discord section
|
#discord section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -604,6 +702,9 @@ Token="Yourtokenhere"
|
|||||||
#REQUIRED
|
#REQUIRED
|
||||||
Server="yourservername"
|
Server="yourservername"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Shows title, description and URL of embedded messages (sent by other bots)
|
#Shows title, description and URL of embedded messages (sent by other bots)
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowEmbeds=false
|
ShowEmbeds=false
|
||||||
@@ -653,15 +754,20 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -670,6 +776,11 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#telegram section
|
#telegram section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -684,9 +795,14 @@ StripNick=false
|
|||||||
#REQUIRED
|
#REQUIRED
|
||||||
Token="Yourtokenhere"
|
Token="Yourtokenhere"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
#Only supported format is "HTML", messages will be sent in html parsemode.
|
#Supported formats are "HTML", "Markdown" and "HTMLNick"
|
||||||
#See https://core.telegram.org/bots/api#html-style
|
#See https://core.telegram.org/bots/api#html-style
|
||||||
|
#See https://core.telegram.org/bots/api#markdown-style
|
||||||
|
#HTMLNick only allows HTML for the nick, the message itself will be html-escaped
|
||||||
MessageFormat=""
|
MessageFormat=""
|
||||||
|
|
||||||
#If enabled use the "First Name" as username. If this is empty use the Username
|
#If enabled use the "First Name" as username. If this is empty use the Username
|
||||||
@@ -701,6 +817,14 @@ UseFirstName=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
UseInsecureURL=false
|
UseInsecureURL=false
|
||||||
|
|
||||||
|
#Disable quoted/reply messages
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
QuoteDisable=false
|
||||||
|
|
||||||
|
#Format quoted/reply messages
|
||||||
|
#OPTIONAL (default "{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})")
|
||||||
|
QuoteFormat="{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})"
|
||||||
|
|
||||||
#Disable sending of edits to other bridges
|
#Disable sending of edits to other bridges
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
EditDisable=false
|
EditDisable=false
|
||||||
@@ -737,15 +861,25 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
|
#
|
||||||
|
#WARNING: if you have set MessageFormat="HTML" be sure that this format matches the guidelines
|
||||||
|
#on https://core.telegram.org/bots/api#html-style otherwise the message will not go through to
|
||||||
|
#telegram! eg <{NICK}> should be <{NICK}>
|
||||||
|
#
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -754,6 +888,11 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#rocketchat section
|
#rocketchat section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -787,6 +926,9 @@ NoTLS=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
SkipTLSVerify=true
|
SkipTLSVerify=true
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Whether to prefix messages from other bridges to rocketchat with the sender's nick.
|
#Whether to prefix messages from other bridges to rocketchat with the sender's nick.
|
||||||
#Useful if username overrides for incoming webhooks isn't enabled on the
|
#Useful if username overrides for incoming webhooks isn't enabled on the
|
||||||
#rocketchat server. If you set PrefixMessagesWithNick to true, each message
|
#rocketchat server. If you set PrefixMessagesWithNick to true, each message
|
||||||
@@ -822,15 +964,20 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -839,6 +986,11 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#matrix section
|
#matrix section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -864,6 +1016,9 @@ Password="yourpass"
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
NoHomeServerSuffix=false
|
NoHomeServerSuffix=false
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Whether to prefix messages from other bridges to matrix with the sender's nick.
|
#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
|
#Useful if username overrides for incoming webhooks isn't enabled on the
|
||||||
#matrix server. If you set PrefixMessagesWithNick to true, each message
|
#matrix server. If you set PrefixMessagesWithNick to true, each message
|
||||||
@@ -899,15 +1054,20 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -916,6 +1076,11 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#steam section
|
#steam section
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -935,6 +1100,9 @@ Password="yourpass"
|
|||||||
#OPTIONAL
|
#OPTIONAL
|
||||||
Authcode="ABCE12"
|
Authcode="ABCE12"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#Whether to prefix messages from other bridges to matrix with the sender's nick.
|
#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
|
#Useful if username overrides for incoming webhooks isn't enabled on the
|
||||||
#matrix server. If you set PrefixMessagesWithNick to true, each message
|
#matrix server. If you set PrefixMessagesWithNick to true, each message
|
||||||
@@ -970,15 +1138,20 @@ ReplaceMessages=[ ["cat","dog"] ]
|
|||||||
#optional (default empty)
|
#optional (default empty)
|
||||||
ReplaceNicks=[ ["user--","user"] ]
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
#Enable to show users joins/parts from other bridges
|
#Enable to show users joins/parts from other bridges
|
||||||
#Only works hiding/show messages from irc and mattermost bridge for now
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
@@ -987,6 +1160,95 @@ ShowJoinPart=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
#zulip section
|
||||||
|
###################################################################
|
||||||
|
[zulip]
|
||||||
|
#You can configure multiple servers "[zulip.name]" or "[zulip.name2]"
|
||||||
|
#In this example we use [zulip.streamchat]
|
||||||
|
#REQUIRED
|
||||||
|
|
||||||
|
[zulip.streamchat]
|
||||||
|
#Token to connect with zulip API (called bot API key in Settings - Your bots)
|
||||||
|
#REQUIRED
|
||||||
|
Token="Yourtokenhere"
|
||||||
|
|
||||||
|
#Username of the bot, normally called yourbot-bot@yourserver.zulipchat.com
|
||||||
|
#See username in Settings - Your bots
|
||||||
|
#REQUIRED
|
||||||
|
Login="yourbot-bot@yourserver.zulipchat.com"
|
||||||
|
|
||||||
|
#Servername of your zulip instance
|
||||||
|
#REQUIRED
|
||||||
|
Server="https://yourserver.zulipchat.com"
|
||||||
|
|
||||||
|
#Topic of the messages matterbridge will use
|
||||||
|
#OPTIONAL (default "matterbridge")
|
||||||
|
Topic="matterbridge"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
|
#Nicks you want to ignore.
|
||||||
|
#Messages from those users will not be sent to other bridges.
|
||||||
|
#OPTIONAL
|
||||||
|
IgnoreNicks="spammer1 spammer2"
|
||||||
|
|
||||||
|
#Messages you want to ignore.
|
||||||
|
#Messages matching these regexp will be ignored and not sent to other bridges
|
||||||
|
#See https://regex-golang.appspot.com/assets/html/index.html for more regex info
|
||||||
|
#OPTIONAL (example below ignores messages starting with ~~ or messages containing badword
|
||||||
|
IgnoreMessages="^~~ badword"
|
||||||
|
|
||||||
|
#messages you want to replace.
|
||||||
|
#it replaces outgoing messages from the bridge.
|
||||||
|
#so you need to place it by the sending bridge definition.
|
||||||
|
#regular expressions supported
|
||||||
|
#some examples:
|
||||||
|
#this replaces cat => dog and sleep => awake
|
||||||
|
#replacemessages=[ ["cat","dog"], ["sleep","awake"] ]
|
||||||
|
#this replaces every number with number. 123 => numbernumbernumber
|
||||||
|
#replacemessages=[ ["[0-9]","number"] ]
|
||||||
|
#optional (default empty)
|
||||||
|
ReplaceMessages=[ ["cat","dog"] ]
|
||||||
|
|
||||||
|
#nicks you want to replace.
|
||||||
|
#see replacemessages for syntaxa
|
||||||
|
#optional (default empty)
|
||||||
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
|
#RemoteNickFormat defines how remote users appear on this bridge
|
||||||
|
#The string "{NICK}" (case sensitive) will be replaced by the actual nick / username.
|
||||||
|
#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
|
||||||
|
#OPTIONAL (default empty)
|
||||||
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
|
#Enable to show users joins/parts from other bridges
|
||||||
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowJoinPart=false
|
||||||
|
|
||||||
|
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
||||||
|
#It will strip other characters from the nick
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#API
|
#API
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -1008,9 +1270,14 @@ Buffer=1000
|
|||||||
#OPTIONAL (no authorization if token is empty)
|
#OPTIONAL (no authorization if token is empty)
|
||||||
Token="mytoken"
|
Token="mytoken"
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="{NICK}"
|
RemoteNickFormat="{NICK}"
|
||||||
@@ -1022,9 +1289,14 @@ RemoteNickFormat="{NICK}"
|
|||||||
###################################################################
|
###################################################################
|
||||||
# Settings here are defaults that each protocol can override
|
# Settings here are defaults that each protocol can override
|
||||||
[general]
|
[general]
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#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 / username.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#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
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
@@ -1035,10 +1307,13 @@ RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
|||||||
StripNick=false
|
StripNick=false
|
||||||
|
|
||||||
|
|
||||||
#MediaServerUpload and MediaServerDownload are used for uploading images/files/video to
|
#MediaServerUpload (or MediaDownloadPath) and MediaServerDownload are used for uploading
|
||||||
#a remote "mediaserver" (a webserver like caddy for example).
|
#images/files/video to a remote "mediaserver" (a webserver like caddy for example).
|
||||||
#When configured images/files uploaded on bridges like mattermost,slack, telegram will be downloaded
|
#When configured images/files uploaded on bridges like mattermost, slack, telegram will be
|
||||||
#and uploaded again to MediaServerUpload URL
|
#downloaded and uploaded again to MediaServerUpload URL
|
||||||
|
#MediaDownloadPath is the filesystem path where the media file will be placed, instead of uploaded,
|
||||||
|
#for if Matterbridge has write access to the directory your webserver is serving.
|
||||||
|
#It is an alternative to MediaServerUpload.
|
||||||
#The MediaServerDownload will be used so that bridges without native uploading support:
|
#The MediaServerDownload will be used so that bridges without native uploading support:
|
||||||
#gitter, irc and xmpp will be shown links to the files on MediaServerDownload
|
#gitter, irc and xmpp will be shown links to the files on MediaServerDownload
|
||||||
#
|
#
|
||||||
@@ -1046,6 +1321,8 @@ StripNick=false
|
|||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
MediaServerUpload="https://user:pass@yourserver.com/upload"
|
MediaServerUpload="https://user:pass@yourserver.com/upload"
|
||||||
#OPTIONAL (default empty)
|
#OPTIONAL (default empty)
|
||||||
|
MediaDownloadPath="/srv/http/yourserver.com/public/download"
|
||||||
|
#OPTIONAL (default empty)
|
||||||
MediaServerDownload="https://youserver.com/download"
|
MediaServerDownload="https://youserver.com/download"
|
||||||
|
|
||||||
#MediaDownloadSize is the maximum size of attachments, videos, images
|
#MediaDownloadSize is the maximum size of attachments, videos, images
|
||||||
@@ -1053,11 +1330,17 @@ MediaServerDownload="https://youserver.com/download"
|
|||||||
#eg downloading from slack to upload it to mattermost
|
#eg downloading from slack to upload it to mattermost
|
||||||
#
|
#
|
||||||
#It will only download from bridges that don't have public links available, which are for the moment
|
#It will only download from bridges that don't have public links available, which are for the moment
|
||||||
#slack, telegram and matrix
|
#slack, telegram, matrix and mattermost
|
||||||
#
|
#
|
||||||
#Optional (default 1000000 (1 megabyte))
|
#OPTIONAL (default 1000000 (1 megabyte))
|
||||||
MediaDownloadSize=1000000
|
MediaDownloadSize=1000000
|
||||||
|
|
||||||
|
#MediaDownloadBlacklist allows you to blacklist specific files from being downloaded.
|
||||||
|
#Filenames matching these regexp will not be download/uploaded to the mediaserver
|
||||||
|
#You can use regex for this, see https://regex-golang.appspot.com/assets/html/index.html for more regex info
|
||||||
|
#OPTIONAL (default empty)
|
||||||
|
MediaDownloadBlacklist=[".html$",".htm$"]
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#Gateway configuration
|
#Gateway configuration
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -1094,6 +1377,7 @@ enable=true
|
|||||||
#gitter - username/room
|
#gitter - username/room
|
||||||
#xmpp - channel
|
#xmpp - channel
|
||||||
#slack - channel (without the #)
|
#slack - channel (without the #)
|
||||||
|
# - ID:C123456 (where C123456 is the channel ID) does not work with webhook
|
||||||
#discord - channel (without the #)
|
#discord - channel (without the #)
|
||||||
# - ID:123456789 (where 123456789 is the channel ID)
|
# - ID:123456789 (where 123456789 is the channel ID)
|
||||||
# (https://github.com/42wim/matterbridge/issues/57)
|
# (https://github.com/42wim/matterbridge/issues/57)
|
||||||
@@ -1105,13 +1389,14 @@ enable=true
|
|||||||
# - encrypted rooms are not supported in matrix
|
# - encrypted rooms are not supported in matrix
|
||||||
#steam - chatid (a large number).
|
#steam - chatid (a large number).
|
||||||
# The number in the URL when you click "enter chat room" in the browser
|
# The number in the URL when you click "enter chat room" in the browser
|
||||||
|
#zulip - stream (without the #)
|
||||||
#
|
#
|
||||||
#REQUIRED
|
#REQUIRED
|
||||||
channel="#testing"
|
channel="#testing"
|
||||||
|
|
||||||
#OPTIONAL - only used for IRC protocol at the moment
|
#OPTIONAL - only used for IRC and XMPP protocols at the moment
|
||||||
[gateway.in.options]
|
[gateway.in.options]
|
||||||
#OPTIONAL - your irc channel key
|
#OPTIONAL - your irc / xmpp channel key
|
||||||
key="yourkey"
|
key="yourkey"
|
||||||
|
|
||||||
|
|
||||||
@@ -1120,9 +1405,9 @@ enable=true
|
|||||||
account="irc.freenode"
|
account="irc.freenode"
|
||||||
channel="#testing"
|
channel="#testing"
|
||||||
|
|
||||||
#OPTIONAL - only used for IRC protocol at the moment
|
#OPTIONAL - only used for IRC and XMPP protocols at the moment
|
||||||
[gateway.out.options]
|
[gateway.out.options]
|
||||||
#OPTIONAL - your irc channel key
|
#OPTIONAL - your irc / xmpp channel key
|
||||||
key="yourkey"
|
key="yourkey"
|
||||||
|
|
||||||
#[[gateway.inout]] can be used when then channel will be used to receive from
|
#[[gateway.inout]] can be used when then channel will be used to receive from
|
||||||
@@ -1131,9 +1416,9 @@ enable=true
|
|||||||
account="mattermost.work"
|
account="mattermost.work"
|
||||||
channel="off-topic"
|
channel="off-topic"
|
||||||
|
|
||||||
#OPTIONAL - only used for IRC protocol at the moment
|
#OPTIONAL - only used for IRC and XMPP protocols at the moment
|
||||||
[gateway.inout.options]
|
[gateway.inout.options]
|
||||||
#OPTIONAL - your irc channel key
|
#OPTIONAL - your irc / xmpp channel key
|
||||||
key="yourkey"
|
key="yourkey"
|
||||||
|
|
||||||
[[gateway.inout]]
|
[[gateway.inout]]
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
prefixed "github.com/matterbridge/logrus-prefixed-formatter"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/hashicorp/golang-lru"
|
"github.com/hashicorp/golang-lru"
|
||||||
@@ -73,12 +74,16 @@ type MMClient struct {
|
|||||||
func New(login, pass, team, server string) *MMClient {
|
func New(login, pass, team, server string) *MMClient {
|
||||||
cred := &Credentials{Login: login, Pass: pass, Team: team, Server: server}
|
cred := &Credentials{Login: login, Pass: pass, Team: team, Server: server}
|
||||||
mmclient := &MMClient{Credentials: cred, MessageChan: make(chan *Message, 100), Users: make(map[string]*model.User)}
|
mmclient := &MMClient{Credentials: cred, MessageChan: make(chan *Message, 100), Users: make(map[string]*model.User)}
|
||||||
mmclient.log = log.WithFields(log.Fields{"module": "matterclient"})
|
log.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true})
|
||||||
log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
|
mmclient.log = log.WithFields(log.Fields{"prefix": "matterclient"})
|
||||||
mmclient.lruCache, _ = lru.New(500)
|
mmclient.lruCache, _ = lru.New(500)
|
||||||
return mmclient
|
return mmclient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MMClient) SetDebugLog() {
|
||||||
|
log.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: false, ForceFormatting: true})
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MMClient) SetLogLevel(level string) {
|
func (m *MMClient) SetLogLevel(level string) {
|
||||||
l, err := log.ParseLevel(level)
|
l, err := log.ParseLevel(level)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -185,7 +190,11 @@ func (m *MMClient) Login() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m.Team == nil {
|
if m.Team == nil {
|
||||||
return errors.New("team not found")
|
validTeamNames := make([]string, len(m.OtherTeams))
|
||||||
|
for i, t := range m.OtherTeams {
|
||||||
|
validTeamNames[i] = t.Team.Name
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Team '%s' not found in %v", m.Credentials.Team, validTeamNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.wsConnect()
|
m.wsConnect()
|
||||||
@@ -301,6 +310,11 @@ func (m *MMClient) parseMessage(rmsg *Message) {
|
|||||||
switch rmsg.Raw.Event {
|
switch rmsg.Raw.Event {
|
||||||
case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED, model.WEBSOCKET_EVENT_POST_DELETED:
|
case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED, model.WEBSOCKET_EVENT_POST_DELETED:
|
||||||
m.parseActionPost(rmsg)
|
m.parseActionPost(rmsg)
|
||||||
|
case "user_updated":
|
||||||
|
user := rmsg.Raw.Data["user"].(map[string]interface{})
|
||||||
|
if _, ok := user["id"].(string); ok {
|
||||||
|
m.UpdateUser(user["id"].(string))
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
case model.ACTION_USER_REMOVED:
|
case model.ACTION_USER_REMOVED:
|
||||||
m.handleWsActionUserRemoved(&rmsg)
|
m.handleWsActionUserRemoved(&rmsg)
|
||||||
@@ -565,7 +579,7 @@ func (m *MMClient) GetFileLinks(filenames []string) []string {
|
|||||||
res, resp := m.Client.GetFileLink(f)
|
res, resp := m.Client.GetFileLink(f)
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
// public links is probably disabled, create the link ourselves
|
// public links is probably disabled, create the link ourselves
|
||||||
output = append(output, uriScheme+m.Credentials.Server+model.API_URL_SUFFIX_V3+"/files/"+f+"/get")
|
output = append(output, uriScheme+m.Credentials.Server+model.API_URL_SUFFIX_V4+"/files/"+f)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
output = append(output, res)
|
output = append(output, res)
|
||||||
@@ -585,9 +599,9 @@ func (m *MMClient) UpdateChannelHeader(channelId string, header string) {
|
|||||||
func (m *MMClient) UpdateLastViewed(channelId string) {
|
func (m *MMClient) UpdateLastViewed(channelId string) {
|
||||||
m.log.Debugf("posting lastview %#v", channelId)
|
m.log.Debugf("posting lastview %#v", channelId)
|
||||||
view := &model.ChannelView{ChannelId: channelId}
|
view := &model.ChannelView{ChannelId: channelId}
|
||||||
res, _ := m.Client.ViewChannel(m.User.Id, view)
|
_, resp := m.Client.ViewChannel(m.User.Id, view)
|
||||||
if !res {
|
if resp.Error != nil {
|
||||||
m.log.Errorf("ChannelView update for %s failed", channelId)
|
m.log.Errorf("ChannelView update for %s failed: %s", channelId, resp.Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,6 +755,16 @@ func (m *MMClient) GetUser(userId string) *model.User {
|
|||||||
return m.Users[userId]
|
return m.Users[userId]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MMClient) UpdateUser(userId string) {
|
||||||
|
m.Lock()
|
||||||
|
defer m.Unlock()
|
||||||
|
res, resp := m.Client.GetUser(userId, "")
|
||||||
|
if resp.Error != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.Users[userId] = res
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MMClient) GetUserName(userId string) string {
|
func (m *MMClient) GetUserName(userId string) string {
|
||||||
user := m.GetUser(userId)
|
user := m.GetUser(userId)
|
||||||
if user != nil {
|
if user != nil {
|
||||||
@@ -749,6 +773,14 @@ func (m *MMClient) GetUserName(userId string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MMClient) GetNickName(userId string) string {
|
||||||
|
user := m.GetUser(userId)
|
||||||
|
if user != nil {
|
||||||
|
return user.Nickname
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MMClient) GetStatus(userId string) string {
|
func (m *MMClient) GetStatus(userId string) string {
|
||||||
res, resp := m.Client.GetUserStatus(userId, "")
|
res, resp := m.Client.GetUserStatus(userId, "")
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
@@ -763,6 +795,14 @@ func (m *MMClient) GetStatus(userId string) string {
|
|||||||
return "offline"
|
return "offline"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MMClient) UpdateStatus(userId string, status string) error {
|
||||||
|
_, resp := m.Client.UpdateUserStatus(userId, &model.Status{Status: status})
|
||||||
|
if resp.Error != nil {
|
||||||
|
return resp.Error
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MMClient) GetStatuses() map[string]string {
|
func (m *MMClient) GetStatuses() map[string]string {
|
||||||
var ids []string
|
var ids []string
|
||||||
statuses := make(map[string]string)
|
statuses := make(map[string]string)
|
||||||
@@ -900,7 +940,8 @@ func supportedVersion(version string) bool {
|
|||||||
if strings.HasPrefix(version, "3.8.0") ||
|
if strings.HasPrefix(version, "3.8.0") ||
|
||||||
strings.HasPrefix(version, "3.9.0") ||
|
strings.HasPrefix(version, "3.9.0") ||
|
||||||
strings.HasPrefix(version, "3.10.0") ||
|
strings.HasPrefix(version, "3.10.0") ||
|
||||||
strings.HasPrefix(version, "4.") {
|
strings.HasPrefix(version, "4.") ||
|
||||||
|
strings.HasPrefix(version, "5.") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/schema"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/schema"
|
||||||
|
"github.com/nlopes/slack"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OMessage for mattermost incoming webhook. (send to mattermost)
|
// OMessage for mattermost incoming webhook. (send to mattermost)
|
||||||
@@ -22,7 +24,7 @@ type OMessage struct {
|
|||||||
IconEmoji string `json:"icon_emoji,omitempty"`
|
IconEmoji string `json:"icon_emoji,omitempty"`
|
||||||
UserName string `json:"username,omitempty"`
|
UserName string `json:"username,omitempty"`
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
Attachments interface{} `json:"attachments,omitempty"`
|
Attachments []slack.Attachment `json:"attachments,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Props map[string]interface{} `json:"props"`
|
Props map[string]interface{} `json:"props"`
|
||||||
}
|
}
|
||||||
|
|||||||
3
vendor/github.com/42wim/go-gitter/.gitignore
generated
vendored
Normal file
3
vendor/github.com/42wim/go-gitter/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.idea
|
||||||
|
/test
|
||||||
|
app.yaml
|
||||||
154
vendor/github.com/42wim/go-gitter/README.md
generated
vendored
Normal file
154
vendor/github.com/42wim/go-gitter/README.md
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
# gitter
|
||||||
|
Gitter API in Go
|
||||||
|
https://developer.gitter.im
|
||||||
|
|
||||||
|
#### Install
|
||||||
|
|
||||||
|
`go get github.com/sromku/go-gitter`
|
||||||
|
|
||||||
|
- [Initialize](#initialize)
|
||||||
|
- [Users](#users)
|
||||||
|
- [Rooms](#rooms)
|
||||||
|
- [Messages](#messages)
|
||||||
|
- [Stream](#stream)
|
||||||
|
- [Faye (Experimental)](#faye-experimental)
|
||||||
|
- [Debug](#debug)
|
||||||
|
- [App Engine](#app-engine)
|
||||||
|
|
||||||
|
##### Initialize
|
||||||
|
``` Go
|
||||||
|
api := gitter.New("YOUR_ACCESS_TOKEN")
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Users
|
||||||
|
|
||||||
|
- Get current user
|
||||||
|
|
||||||
|
``` Go
|
||||||
|
user, err := api.GetUser()
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Rooms
|
||||||
|
|
||||||
|
- Get all rooms
|
||||||
|
``` Go
|
||||||
|
rooms, err := api.GetRooms()
|
||||||
|
```
|
||||||
|
|
||||||
|
- Get room by id
|
||||||
|
``` Go
|
||||||
|
room, err := api.GetRoom("roomID")
|
||||||
|
```
|
||||||
|
|
||||||
|
- Get rooms of some user
|
||||||
|
``` Go
|
||||||
|
rooms, err := api.GetRooms("userID")
|
||||||
|
```
|
||||||
|
|
||||||
|
- Join room
|
||||||
|
``` Go
|
||||||
|
room, err := api.JoinRoom("roomID", "userID")
|
||||||
|
```
|
||||||
|
|
||||||
|
- Leave room
|
||||||
|
``` Go
|
||||||
|
room, err := api.LeaveRoom("roomID", "userID")
|
||||||
|
```
|
||||||
|
|
||||||
|
- Get room id
|
||||||
|
``` Go
|
||||||
|
id, err := api.GetRoomId("room/uri")
|
||||||
|
```
|
||||||
|
|
||||||
|
- Search gitter rooms
|
||||||
|
``` Go
|
||||||
|
rooms, err := api.SearchRooms("search/string")
|
||||||
|
```
|
||||||
|
##### Messages
|
||||||
|
|
||||||
|
- Get messages of room
|
||||||
|
``` Go
|
||||||
|
messages, err := api.GetMessages("roomID", nil)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Get one message
|
||||||
|
``` Go
|
||||||
|
message, err := api.GetMessage("roomID", "messageID")
|
||||||
|
```
|
||||||
|
|
||||||
|
- Send message
|
||||||
|
``` Go
|
||||||
|
err := api.SendMessage("roomID", "free chat text")
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Stream
|
||||||
|
|
||||||
|
Create stream to the room and start listening to incoming messages
|
||||||
|
|
||||||
|
``` Go
|
||||||
|
stream := api.Stream(room.Id)
|
||||||
|
go api.Listen(stream)
|
||||||
|
|
||||||
|
for {
|
||||||
|
event := <-stream.Event
|
||||||
|
switch ev := event.Data.(type) {
|
||||||
|
case *gitter.MessageReceived:
|
||||||
|
fmt.Println(ev.Message.From.Username + ": " + ev.Message.Text)
|
||||||
|
case *gitter.GitterConnectionClosed:
|
||||||
|
// connection was closed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Close stream connection
|
||||||
|
|
||||||
|
``` Go
|
||||||
|
stream.Close()
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Faye (Experimental)
|
||||||
|
|
||||||
|
``` Go
|
||||||
|
faye := api.Faye(room.ID)
|
||||||
|
go faye.Listen()
|
||||||
|
|
||||||
|
for {
|
||||||
|
event := <-faye.Event
|
||||||
|
switch ev := event.Data.(type) {
|
||||||
|
case *gitter.MessageReceived:
|
||||||
|
fmt.Println(ev.Message.From.Username + ": " + ev.Message.Text)
|
||||||
|
case *gitter.GitterConnectionClosed: //this one is never called in Faye
|
||||||
|
// connection was closed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Debug
|
||||||
|
|
||||||
|
You can print the internal errors by enabling debug to true
|
||||||
|
|
||||||
|
``` Go
|
||||||
|
api.SetDebug(true, nil)
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also define your own `io.Writer` in case you want to persist the logs somewhere.
|
||||||
|
For example keeping the errors on file
|
||||||
|
|
||||||
|
``` Go
|
||||||
|
logFile, err := os.Create("gitter.log")
|
||||||
|
api.SetDebug(true, logFile)
|
||||||
|
```
|
||||||
|
|
||||||
|
##### App Engine
|
||||||
|
|
||||||
|
Initialize app engine client and continue as usual
|
||||||
|
|
||||||
|
``` Go
|
||||||
|
c := appengine.NewContext(r)
|
||||||
|
client := urlfetch.Client(c)
|
||||||
|
|
||||||
|
api := gitter.New("YOUR_ACCESS_TOKEN")
|
||||||
|
api.SetClient(client)
|
||||||
|
```
|
||||||
|
|
||||||
|
[Documentation](https://godoc.org/github.com/sromku/go-gitter)
|
||||||
27
vendor/github.com/42wim/go-ircevent/LICENSE
generated
vendored
27
vendor/github.com/42wim/go-ircevent/LICENSE
generated
vendored
@@ -1,27 +0,0 @@
|
|||||||
// Copyright (c) 2009 Thomas Jager. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
578
vendor/github.com/42wim/go-ircevent/irc.go
generated
vendored
578
vendor/github.com/42wim/go-ircevent/irc.go
generated
vendored
@@ -1,578 +0,0 @@
|
|||||||
// Copyright 2009 Thomas Jager <mail@jager.no> All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
/*
|
|
||||||
This package provides an event based IRC client library. It allows to
|
|
||||||
register callbacks for the events you need to handle. Its features
|
|
||||||
include handling standard CTCP, reconnecting on errors and detecting
|
|
||||||
stones servers.
|
|
||||||
Details of the IRC protocol can be found in the following RFCs:
|
|
||||||
https://tools.ietf.org/html/rfc1459
|
|
||||||
https://tools.ietf.org/html/rfc2810
|
|
||||||
https://tools.ietf.org/html/rfc2811
|
|
||||||
https://tools.ietf.org/html/rfc2812
|
|
||||||
https://tools.ietf.org/html/rfc2813
|
|
||||||
The details of the client-to-client protocol (CTCP) can be found here: http://www.irchelp.org/irchelp/rfc/ctcpspec.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
package irc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
VERSION = "go-ircevent v2.1"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrDisconnected = errors.New("Disconnect Called")
|
|
||||||
|
|
||||||
// Read data from a connection. To be used as a goroutine.
|
|
||||||
func (irc *Connection) readLoop() {
|
|
||||||
defer irc.Done()
|
|
||||||
br := bufio.NewReaderSize(irc.socket, 512)
|
|
||||||
|
|
||||||
errChan := irc.ErrorChan()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-irc.end:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
// Set a read deadline based on the combined timeout and ping frequency
|
|
||||||
// We should ALWAYS have received a response from the server within the timeout
|
|
||||||
// after our own pings
|
|
||||||
if irc.socket != nil {
|
|
||||||
irc.socket.SetReadDeadline(time.Now().Add(irc.Timeout + irc.PingFreq))
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := br.ReadString('\n')
|
|
||||||
|
|
||||||
// We got past our blocking read, so bin timeout
|
|
||||||
if irc.socket != nil {
|
|
||||||
var zero time.Time
|
|
||||||
irc.socket.SetReadDeadline(zero)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
errChan <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if irc.Debug {
|
|
||||||
irc.Log.Printf("<-- %s\n", strings.TrimSpace(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
irc.Lock()
|
|
||||||
irc.lastMessage = time.Now()
|
|
||||||
irc.Unlock()
|
|
||||||
event, err := parseToEvent(msg)
|
|
||||||
event.Connection = irc
|
|
||||||
if err == nil {
|
|
||||||
/* XXX: len(args) == 0: args should be empty */
|
|
||||||
irc.RunCallbacks(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unescape tag values as defined in the IRCv3.2 message tags spec
|
|
||||||
// http://ircv3.net/specs/core/message-tags-3.2.html
|
|
||||||
func unescapeTagValue(value string) string {
|
|
||||||
value = strings.Replace(value, "\\:", ";", -1)
|
|
||||||
value = strings.Replace(value, "\\s", " ", -1)
|
|
||||||
value = strings.Replace(value, "\\\\", "\\", -1)
|
|
||||||
value = strings.Replace(value, "\\r", "\r", -1)
|
|
||||||
value = strings.Replace(value, "\\n", "\n", -1)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
//Parse raw irc messages
|
|
||||||
func parseToEvent(msg string) (*Event, error) {
|
|
||||||
msg = strings.TrimSuffix(msg, "\n") //Remove \r\n
|
|
||||||
msg = strings.TrimSuffix(msg, "\r")
|
|
||||||
event := &Event{Raw: msg}
|
|
||||||
if len(msg) < 5 {
|
|
||||||
return nil, errors.New("Malformed msg from server")
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg[0] == '@' {
|
|
||||||
// IRCv3 Message Tags
|
|
||||||
if i := strings.Index(msg, " "); i > -1 {
|
|
||||||
event.Tags = make(map[string]string)
|
|
||||||
tags := strings.Split(msg[1:i], ";")
|
|
||||||
for _, data := range tags {
|
|
||||||
parts := strings.SplitN(data, "=", 2)
|
|
||||||
if len(parts) == 1 {
|
|
||||||
event.Tags[parts[0]] = ""
|
|
||||||
} else {
|
|
||||||
event.Tags[parts[0]] = unescapeTagValue(parts[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg = msg[i+1 : len(msg)]
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("Malformed msg from server")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg[0] == ':' {
|
|
||||||
if i := strings.Index(msg, " "); i > -1 {
|
|
||||||
event.Source = msg[1:i]
|
|
||||||
msg = msg[i+1 : len(msg)]
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("Malformed msg from server")
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, j := strings.Index(event.Source, "!"), strings.Index(event.Source, "@"); i > -1 && j > -1 && i < j {
|
|
||||||
event.Nick = event.Source[0:i]
|
|
||||||
event.User = event.Source[i+1 : j]
|
|
||||||
event.Host = event.Source[j+1 : len(event.Source)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
split := strings.SplitN(msg, " :", 2)
|
|
||||||
args := strings.Split(split[0], " ")
|
|
||||||
event.Code = strings.ToUpper(args[0])
|
|
||||||
event.Arguments = args[1:]
|
|
||||||
if len(split) > 1 {
|
|
||||||
event.Arguments = append(event.Arguments, split[1])
|
|
||||||
}
|
|
||||||
return event, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop to write to a connection. To be used as a goroutine.
|
|
||||||
func (irc *Connection) writeLoop() {
|
|
||||||
defer irc.Done()
|
|
||||||
errChan := irc.ErrorChan()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-irc.end:
|
|
||||||
return
|
|
||||||
case b, ok := <-irc.pwrite:
|
|
||||||
if !ok || b == "" || irc.socket == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if irc.Debug {
|
|
||||||
irc.Log.Printf("--> %s\n", strings.TrimSpace(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a write deadline based on the time out
|
|
||||||
irc.socket.SetWriteDeadline(time.Now().Add(irc.Timeout))
|
|
||||||
|
|
||||||
_, err := irc.socket.Write([]byte(b))
|
|
||||||
|
|
||||||
// Past blocking write, bin timeout
|
|
||||||
var zero time.Time
|
|
||||||
irc.socket.SetWriteDeadline(zero)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
errChan <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pings the server if we have not received any messages for 5 minutes
|
|
||||||
// to keep the connection alive. To be used as a goroutine.
|
|
||||||
func (irc *Connection) pingLoop() {
|
|
||||||
defer irc.Done()
|
|
||||||
ticker := time.NewTicker(1 * time.Minute) // Tick every minute for monitoring
|
|
||||||
ticker2 := time.NewTicker(irc.PingFreq) // Tick at the ping frequency.
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
//Ping if we haven't received anything from the server within the keep alive period
|
|
||||||
if time.Since(irc.lastMessage) >= irc.KeepAlive {
|
|
||||||
irc.SendRawf("PING %d", time.Now().UnixNano())
|
|
||||||
}
|
|
||||||
case <-ticker2.C:
|
|
||||||
//Ping at the ping frequency
|
|
||||||
irc.SendRawf("PING %d", time.Now().UnixNano())
|
|
||||||
//Try to recapture nickname if it's not as configured.
|
|
||||||
irc.Lock()
|
|
||||||
if irc.nick != irc.nickcurrent {
|
|
||||||
irc.nickcurrent = irc.nick
|
|
||||||
irc.SendRawf("NICK %s", irc.nick)
|
|
||||||
}
|
|
||||||
irc.Unlock()
|
|
||||||
case <-irc.end:
|
|
||||||
ticker.Stop()
|
|
||||||
ticker2.Stop()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (irc *Connection) isQuitting() bool {
|
|
||||||
irc.Lock()
|
|
||||||
defer irc.Unlock()
|
|
||||||
return irc.quit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main loop to control the connection.
|
|
||||||
func (irc *Connection) Loop() {
|
|
||||||
errChan := irc.ErrorChan()
|
|
||||||
connTime := time.Now()
|
|
||||||
for !irc.isQuitting() {
|
|
||||||
err := <-errChan
|
|
||||||
close(irc.end)
|
|
||||||
irc.Wait()
|
|
||||||
for !irc.isQuitting() {
|
|
||||||
irc.Log.Printf("Error, disconnected: %s\n", err)
|
|
||||||
if time.Now().Sub(connTime) < time.Second*5 {
|
|
||||||
irc.Log.Println("Rreconnecting too fast, sleeping 60 seconds")
|
|
||||||
time.Sleep(60 * time.Second)
|
|
||||||
}
|
|
||||||
if err = irc.Reconnect(); err != nil {
|
|
||||||
irc.Log.Printf("Error while reconnecting: %s\n", err)
|
|
||||||
time.Sleep(60 * time.Second)
|
|
||||||
} else {
|
|
||||||
errChan = irc.ErrorChan()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connTime = time.Now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quit the current connection and disconnect from the server
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1.6
|
|
||||||
func (irc *Connection) Quit() {
|
|
||||||
quit := "QUIT"
|
|
||||||
|
|
||||||
if irc.QuitMessage != "" {
|
|
||||||
quit = fmt.Sprintf("QUIT :%s", irc.QuitMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
irc.SendRaw(quit)
|
|
||||||
irc.Lock()
|
|
||||||
irc.stopped = true
|
|
||||||
irc.quit = true
|
|
||||||
irc.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the connection to join a given channel.
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.1
|
|
||||||
func (irc *Connection) Join(channel string) {
|
|
||||||
irc.pwrite <- fmt.Sprintf("JOIN %s\r\n", channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leave a given channel.
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.2
|
|
||||||
func (irc *Connection) Part(channel string) {
|
|
||||||
irc.pwrite <- fmt.Sprintf("PART %s\r\n", channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a notification to a nickname. This is similar to Privmsg but must not receive replies.
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.2
|
|
||||||
func (irc *Connection) Notice(target, message string) {
|
|
||||||
irc.pwrite <- fmt.Sprintf("NOTICE %s :%s\r\n", target, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a formated notification to a nickname.
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.2
|
|
||||||
func (irc *Connection) Noticef(target, format string, a ...interface{}) {
|
|
||||||
irc.Notice(target, fmt.Sprintf(format, a...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send (action) message to a target (channel or nickname).
|
|
||||||
// No clear RFC on this one...
|
|
||||||
func (irc *Connection) Action(target, message string) {
|
|
||||||
irc.pwrite <- fmt.Sprintf("PRIVMSG %s :\001ACTION %s\001\r\n", target, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send formatted (action) message to a target (channel or nickname).
|
|
||||||
func (irc *Connection) Actionf(target, format string, a ...interface{}) {
|
|
||||||
irc.Action(target, fmt.Sprintf(format, a...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send (private) message to a target (channel or nickname).
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.4.1
|
|
||||||
func (irc *Connection) Privmsg(target, message string) {
|
|
||||||
irc.pwrite <- fmt.Sprintf("PRIVMSG %s :%s\r\n", target, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send formated string to specified target (channel or nickname).
|
|
||||||
func (irc *Connection) Privmsgf(target, format string, a ...interface{}) {
|
|
||||||
irc.Privmsg(target, fmt.Sprintf(format, a...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kick <user> from <channel> with <msg>. For no message, pass empty string ("")
|
|
||||||
func (irc *Connection) Kick(user, channel, msg string) {
|
|
||||||
var cmd bytes.Buffer
|
|
||||||
cmd.WriteString(fmt.Sprintf("KICK %s %s", channel, user))
|
|
||||||
if msg != "" {
|
|
||||||
cmd.WriteString(fmt.Sprintf(" :%s", msg))
|
|
||||||
}
|
|
||||||
cmd.WriteString("\r\n")
|
|
||||||
irc.pwrite <- cmd.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kick all <users> from <channel> with <msg>. For no message, pass
|
|
||||||
// empty string ("")
|
|
||||||
func (irc *Connection) MultiKick(users []string, channel string, msg string) {
|
|
||||||
var cmd bytes.Buffer
|
|
||||||
cmd.WriteString(fmt.Sprintf("KICK %s %s", channel, strings.Join(users, ",")))
|
|
||||||
if msg != "" {
|
|
||||||
cmd.WriteString(fmt.Sprintf(" :%s", msg))
|
|
||||||
}
|
|
||||||
cmd.WriteString("\r\n")
|
|
||||||
irc.pwrite <- cmd.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send raw string.
|
|
||||||
func (irc *Connection) SendRaw(message string) {
|
|
||||||
irc.pwrite <- message + "\r\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send raw formated string.
|
|
||||||
func (irc *Connection) SendRawf(format string, a ...interface{}) {
|
|
||||||
irc.SendRaw(fmt.Sprintf(format, a...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set (new) nickname.
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1.2
|
|
||||||
func (irc *Connection) Nick(n string) {
|
|
||||||
irc.nick = n
|
|
||||||
irc.SendRawf("NICK %s", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine nick currently used with the connection.
|
|
||||||
func (irc *Connection) GetNick() string {
|
|
||||||
return irc.nickcurrent
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query information about a particular nickname.
|
|
||||||
// RFC 1459: https://tools.ietf.org/html/rfc1459#section-4.5.2
|
|
||||||
func (irc *Connection) Whois(nick string) {
|
|
||||||
irc.SendRawf("WHOIS %s", nick)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query information about a given nickname in the server.
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.5.1
|
|
||||||
func (irc *Connection) Who(nick string) {
|
|
||||||
irc.SendRawf("WHO %s", nick)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set different modes for a target (channel or nickname).
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.2.3
|
|
||||||
func (irc *Connection) Mode(target string, modestring ...string) {
|
|
||||||
if len(modestring) > 0 {
|
|
||||||
mode := strings.Join(modestring, " ")
|
|
||||||
irc.SendRawf("MODE %s %s", target, mode)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
irc.SendRawf("MODE %s", target)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (irc *Connection) ErrorChan() chan error {
|
|
||||||
return irc.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the connection is connected to an IRC server.
|
|
||||||
func (irc *Connection) Connected() bool {
|
|
||||||
return !irc.stopped
|
|
||||||
}
|
|
||||||
|
|
||||||
// A disconnect sends all buffered messages (if possible),
|
|
||||||
// stops all goroutines and then closes the socket.
|
|
||||||
func (irc *Connection) Disconnect() {
|
|
||||||
if irc.socket != nil {
|
|
||||||
irc.socket.Close()
|
|
||||||
}
|
|
||||||
irc.ErrorChan() <- ErrDisconnected
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconnect to a server using the current connection.
|
|
||||||
func (irc *Connection) Reconnect() error {
|
|
||||||
irc.end = make(chan struct{})
|
|
||||||
return irc.Connect(irc.Server)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to a given server using the current connection configuration.
|
|
||||||
// This function also takes care of identification if a password is provided.
|
|
||||||
// RFC 1459 details: https://tools.ietf.org/html/rfc1459#section-4.1
|
|
||||||
func (irc *Connection) Connect(server string) error {
|
|
||||||
irc.Server = server
|
|
||||||
// mark Server as stopped since there can be an error during connect
|
|
||||||
irc.stopped = true
|
|
||||||
|
|
||||||
// make sure everything is ready for connection
|
|
||||||
if len(irc.Server) == 0 {
|
|
||||||
return errors.New("empty 'server'")
|
|
||||||
}
|
|
||||||
if strings.Count(irc.Server, ":") != 1 {
|
|
||||||
return errors.New("wrong number of ':' in address")
|
|
||||||
}
|
|
||||||
if strings.Index(irc.Server, ":") == 0 {
|
|
||||||
return errors.New("hostname is missing")
|
|
||||||
}
|
|
||||||
if strings.Index(irc.Server, ":") == len(irc.Server)-1 {
|
|
||||||
return errors.New("port missing")
|
|
||||||
}
|
|
||||||
// check for valid range
|
|
||||||
ports := strings.Split(irc.Server, ":")[1]
|
|
||||||
port, err := strconv.Atoi(ports)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("extracting port failed")
|
|
||||||
}
|
|
||||||
if !((port >= 0) && (port <= 65535)) {
|
|
||||||
return errors.New("port number outside valid range")
|
|
||||||
}
|
|
||||||
if irc.Log == nil {
|
|
||||||
return errors.New("'Log' points to nil")
|
|
||||||
}
|
|
||||||
if len(irc.nick) == 0 {
|
|
||||||
return errors.New("empty 'nick'")
|
|
||||||
}
|
|
||||||
if len(irc.user) == 0 {
|
|
||||||
return errors.New("empty 'user'")
|
|
||||||
}
|
|
||||||
|
|
||||||
if irc.UseTLS {
|
|
||||||
dialer := &net.Dialer{Timeout: irc.Timeout}
|
|
||||||
irc.socket, err = tls.DialWithDialer(dialer, "tcp", irc.Server, irc.TLSConfig)
|
|
||||||
} else {
|
|
||||||
irc.socket, err = net.DialTimeout("tcp", irc.Server, irc.Timeout)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
irc.stopped = false
|
|
||||||
irc.Log.Printf("Connected to %s (%s)\n", irc.Server, irc.socket.RemoteAddr())
|
|
||||||
|
|
||||||
irc.pwrite = make(chan string, 10)
|
|
||||||
irc.Error = make(chan error, 2)
|
|
||||||
irc.Add(3)
|
|
||||||
go irc.readLoop()
|
|
||||||
go irc.writeLoop()
|
|
||||||
go irc.pingLoop()
|
|
||||||
if len(irc.Password) > 0 {
|
|
||||||
irc.pwrite <- fmt.Sprintf("PASS %s\r\n", irc.Password)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = irc.negotiateCaps()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
irc.pwrite <- fmt.Sprintf("NICK %s\r\n", irc.nick)
|
|
||||||
irc.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", irc.user, irc.user)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Negotiate IRCv3 capabilities
|
|
||||||
func (irc *Connection) negotiateCaps() error {
|
|
||||||
saslResChan := make(chan *SASLResult)
|
|
||||||
if irc.UseSASL {
|
|
||||||
irc.RequestCaps = append(irc.RequestCaps, "sasl")
|
|
||||||
irc.setupSASLCallbacks(saslResChan)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(irc.RequestCaps) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cap_chan := make(chan bool, len(irc.RequestCaps))
|
|
||||||
irc.AddCallback("CAP", func(e *Event) {
|
|
||||||
if len(e.Arguments) != 3 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
command := e.Arguments[1]
|
|
||||||
|
|
||||||
if command == "LS" {
|
|
||||||
missing_caps := len(irc.RequestCaps)
|
|
||||||
for _, cap_name := range strings.Split(e.Arguments[2], " ") {
|
|
||||||
for _, req_cap := range irc.RequestCaps {
|
|
||||||
if cap_name == req_cap {
|
|
||||||
irc.pwrite <- fmt.Sprintf("CAP REQ :%s\r\n", cap_name)
|
|
||||||
missing_caps--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < missing_caps; i++ {
|
|
||||||
cap_chan <- true
|
|
||||||
}
|
|
||||||
} else if command == "ACK" || command == "NAK" {
|
|
||||||
for _, cap_name := range strings.Split(strings.TrimSpace(e.Arguments[2]), " ") {
|
|
||||||
if cap_name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if command == "ACK" {
|
|
||||||
irc.AcknowledgedCaps = append(irc.AcknowledgedCaps, cap_name)
|
|
||||||
}
|
|
||||||
cap_chan <- true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
irc.pwrite <- "CAP LS\r\n"
|
|
||||||
|
|
||||||
if irc.UseSASL {
|
|
||||||
select {
|
|
||||||
case res := <-saslResChan:
|
|
||||||
if res.Failed {
|
|
||||||
close(saslResChan)
|
|
||||||
return res.Err
|
|
||||||
}
|
|
||||||
case <-time.After(time.Second * 15):
|
|
||||||
close(saslResChan)
|
|
||||||
return errors.New("SASL setup timed out. This shouldn't happen.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for all capabilities to be ACKed or NAKed before ending negotiation
|
|
||||||
for i := 0; i < len(irc.RequestCaps); i++ {
|
|
||||||
<-cap_chan
|
|
||||||
}
|
|
||||||
irc.pwrite <- fmt.Sprintf("CAP END\r\n")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a connection with the (publicly visible) nickname and username.
|
|
||||||
// The nickname is later used to address the user. Returns nil if nick
|
|
||||||
// or user are empty.
|
|
||||||
func IRC(nick, user string) *Connection {
|
|
||||||
// catch invalid values
|
|
||||||
if len(nick) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if len(user) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
irc := &Connection{
|
|
||||||
nick: nick,
|
|
||||||
nickcurrent: nick,
|
|
||||||
user: user,
|
|
||||||
Log: log.New(os.Stdout, "", log.LstdFlags),
|
|
||||||
end: make(chan struct{}),
|
|
||||||
Version: VERSION,
|
|
||||||
KeepAlive: 4 * time.Minute,
|
|
||||||
Timeout: 1 * time.Minute,
|
|
||||||
PingFreq: 15 * time.Minute,
|
|
||||||
SASLMech: "PLAIN",
|
|
||||||
QuitMessage: "",
|
|
||||||
}
|
|
||||||
irc.setupCallbacks()
|
|
||||||
return irc
|
|
||||||
}
|
|
||||||
222
vendor/github.com/42wim/go-ircevent/irc_callback.go
generated
vendored
222
vendor/github.com/42wim/go-ircevent/irc_callback.go
generated
vendored
@@ -1,222 +0,0 @@
|
|||||||
package irc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Register a callback to a connection and event code. A callback is a function
|
|
||||||
// which takes only an Event pointer as parameter. Valid event codes are all
|
|
||||||
// IRC/CTCP commands and error/response codes. This function returns the ID of
|
|
||||||
// the registered callback for later management.
|
|
||||||
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) int {
|
|
||||||
eventcode = strings.ToUpper(eventcode)
|
|
||||||
id := 0
|
|
||||||
if _, ok := irc.events[eventcode]; !ok {
|
|
||||||
irc.events[eventcode] = make(map[int]func(*Event))
|
|
||||||
id = 0
|
|
||||||
} else {
|
|
||||||
id = len(irc.events[eventcode])
|
|
||||||
}
|
|
||||||
irc.events[eventcode][id] = callback
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove callback i (ID) from the given event code. This functions returns
|
|
||||||
// true upon success, false if any error occurs.
|
|
||||||
func (irc *Connection) RemoveCallback(eventcode string, i int) bool {
|
|
||||||
eventcode = strings.ToUpper(eventcode)
|
|
||||||
|
|
||||||
if event, ok := irc.events[eventcode]; ok {
|
|
||||||
if _, ok := event[i]; ok {
|
|
||||||
delete(irc.events[eventcode], i)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
irc.Log.Printf("Event found, but no callback found at id %d\n", i)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
irc.Log.Println("Event not found")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all callbacks from a given event code. It returns true
|
|
||||||
// if given event code is found and cleared.
|
|
||||||
func (irc *Connection) ClearCallback(eventcode string) bool {
|
|
||||||
eventcode = strings.ToUpper(eventcode)
|
|
||||||
|
|
||||||
if _, ok := irc.events[eventcode]; ok {
|
|
||||||
irc.events[eventcode] = make(map[int]func(*Event))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
irc.Log.Println("Event not found")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace callback i (ID) associated with a given event code with a new callback function.
|
|
||||||
func (irc *Connection) ReplaceCallback(eventcode string, i int, callback func(*Event)) {
|
|
||||||
eventcode = strings.ToUpper(eventcode)
|
|
||||||
|
|
||||||
if event, ok := irc.events[eventcode]; ok {
|
|
||||||
if _, ok := event[i]; ok {
|
|
||||||
event[i] = callback
|
|
||||||
return
|
|
||||||
}
|
|
||||||
irc.Log.Printf("Event found, but no callback found at id %d\n", i)
|
|
||||||
}
|
|
||||||
irc.Log.Printf("Event not found. Use AddCallBack\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute all callbacks associated with a given event.
|
|
||||||
func (irc *Connection) RunCallbacks(event *Event) {
|
|
||||||
msg := event.Message()
|
|
||||||
if event.Code == "PRIVMSG" && len(msg) > 2 && msg[0] == '\x01' {
|
|
||||||
event.Code = "CTCP" //Unknown CTCP
|
|
||||||
|
|
||||||
if i := strings.LastIndex(msg, "\x01"); i > 0 {
|
|
||||||
msg = msg[1:i]
|
|
||||||
} else {
|
|
||||||
irc.Log.Printf("Invalid CTCP Message: %s\n", strconv.Quote(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg == "VERSION" {
|
|
||||||
event.Code = "CTCP_VERSION"
|
|
||||||
|
|
||||||
} else if msg == "TIME" {
|
|
||||||
event.Code = "CTCP_TIME"
|
|
||||||
|
|
||||||
} else if strings.HasPrefix(msg, "PING") {
|
|
||||||
event.Code = "CTCP_PING"
|
|
||||||
|
|
||||||
} else if msg == "USERINFO" {
|
|
||||||
event.Code = "CTCP_USERINFO"
|
|
||||||
|
|
||||||
} else if msg == "CLIENTINFO" {
|
|
||||||
event.Code = "CTCP_CLIENTINFO"
|
|
||||||
|
|
||||||
} else if strings.HasPrefix(msg, "ACTION") {
|
|
||||||
event.Code = "CTCP_ACTION"
|
|
||||||
if len(msg) > 6 {
|
|
||||||
msg = msg[7:]
|
|
||||||
} else {
|
|
||||||
msg = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event.Arguments[len(event.Arguments)-1] = msg
|
|
||||||
}
|
|
||||||
|
|
||||||
if callbacks, ok := irc.events[event.Code]; ok {
|
|
||||||
if irc.VerboseCallbackHandler {
|
|
||||||
irc.Log.Printf("%v (%v) >> %#v\n", event.Code, len(callbacks), event)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, callback := range callbacks {
|
|
||||||
callback(event)
|
|
||||||
}
|
|
||||||
} else if irc.VerboseCallbackHandler {
|
|
||||||
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
if callbacks, ok := irc.events["*"]; ok {
|
|
||||||
if irc.VerboseCallbackHandler {
|
|
||||||
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, callback := range callbacks {
|
|
||||||
callback(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up some initial callbacks to handle the IRC/CTCP protocol.
|
|
||||||
func (irc *Connection) setupCallbacks() {
|
|
||||||
irc.events = make(map[string]map[int]func(*Event))
|
|
||||||
|
|
||||||
//Handle error events.
|
|
||||||
irc.AddCallback("ERROR", func(e *Event) { irc.Disconnect() })
|
|
||||||
|
|
||||||
//Handle ping events
|
|
||||||
irc.AddCallback("PING", func(e *Event) { irc.SendRaw("PONG :" + e.Message()) })
|
|
||||||
|
|
||||||
//Version handler
|
|
||||||
irc.AddCallback("CTCP_VERSION", func(e *Event) {
|
|
||||||
irc.SendRawf("NOTICE %s :\x01VERSION %s\x01", e.Nick, irc.Version)
|
|
||||||
})
|
|
||||||
|
|
||||||
irc.AddCallback("CTCP_USERINFO", func(e *Event) {
|
|
||||||
irc.SendRawf("NOTICE %s :\x01USERINFO %s\x01", e.Nick, irc.user)
|
|
||||||
})
|
|
||||||
|
|
||||||
irc.AddCallback("CTCP_CLIENTINFO", func(e *Event) {
|
|
||||||
irc.SendRawf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick)
|
|
||||||
})
|
|
||||||
|
|
||||||
irc.AddCallback("CTCP_TIME", func(e *Event) {
|
|
||||||
ltime := time.Now()
|
|
||||||
irc.SendRawf("NOTICE %s :\x01TIME %s\x01", e.Nick, ltime.String())
|
|
||||||
})
|
|
||||||
|
|
||||||
irc.AddCallback("CTCP_PING", func(e *Event) { irc.SendRawf("NOTICE %s :\x01%s\x01", e.Nick, e.Message()) })
|
|
||||||
|
|
||||||
// 437: ERR_UNAVAILRESOURCE "<nick/channel> :Nick/channel is temporarily unavailable"
|
|
||||||
// Add a _ to current nick. If irc.nickcurrent is empty this cannot
|
|
||||||
// work. It has to be set somewhere first in case the nick is already
|
|
||||||
// taken or unavailable from the beginning.
|
|
||||||
irc.AddCallback("437", func(e *Event) {
|
|
||||||
// If irc.nickcurrent hasn't been set yet, set to irc.nick
|
|
||||||
if irc.nickcurrent == "" {
|
|
||||||
irc.nickcurrent = irc.nick
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(irc.nickcurrent) > 8 {
|
|
||||||
irc.nickcurrent = "_" + irc.nickcurrent
|
|
||||||
} else {
|
|
||||||
irc.nickcurrent = irc.nickcurrent + "_"
|
|
||||||
}
|
|
||||||
irc.SendRawf("NICK %s", irc.nickcurrent)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 433: ERR_NICKNAMEINUSE "<nick> :Nickname is already in use"
|
|
||||||
// Add a _ to current nick.
|
|
||||||
irc.AddCallback("433", func(e *Event) {
|
|
||||||
// If irc.nickcurrent hasn't been set yet, set to irc.nick
|
|
||||||
if irc.nickcurrent == "" {
|
|
||||||
irc.nickcurrent = irc.nick
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(irc.nickcurrent) > 8 {
|
|
||||||
irc.nickcurrent = "_" + irc.nickcurrent
|
|
||||||
} else {
|
|
||||||
irc.nickcurrent = irc.nickcurrent + "_"
|
|
||||||
}
|
|
||||||
irc.SendRawf("NICK %s", irc.nickcurrent)
|
|
||||||
})
|
|
||||||
|
|
||||||
irc.AddCallback("PONG", func(e *Event) {
|
|
||||||
ns, _ := strconv.ParseInt(e.Message(), 10, 64)
|
|
||||||
delta := time.Duration(time.Now().UnixNano() - ns)
|
|
||||||
if irc.Debug {
|
|
||||||
irc.Log.Printf("Lag: %.3f s\n", delta.Seconds())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// NICK Define a nickname.
|
|
||||||
// Set irc.nickcurrent to the new nick actually used in this connection.
|
|
||||||
irc.AddCallback("NICK", func(e *Event) {
|
|
||||||
if e.Nick == irc.nick {
|
|
||||||
irc.nickcurrent = e.Message()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 1: RPL_WELCOME "Welcome to the Internet Relay Network <nick>!<user>@<host>"
|
|
||||||
// Set irc.nickcurrent to the actually used nick in this connection.
|
|
||||||
irc.AddCallback("001", func(e *Event) {
|
|
||||||
irc.Lock()
|
|
||||||
irc.nickcurrent = e.Arguments[0]
|
|
||||||
irc.Unlock()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
53
vendor/github.com/42wim/go-ircevent/irc_sasl.go
generated
vendored
53
vendor/github.com/42wim/go-ircevent/irc_sasl.go
generated
vendored
@@ -1,53 +0,0 @@
|
|||||||
package irc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SASLResult struct {
|
|
||||||
Failed bool
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (irc *Connection) setupSASLCallbacks(result chan<- *SASLResult) {
|
|
||||||
irc.AddCallback("CAP", func(e *Event) {
|
|
||||||
if len(e.Arguments) == 3 {
|
|
||||||
if e.Arguments[1] == "LS" {
|
|
||||||
if !strings.Contains(e.Arguments[2], "sasl") {
|
|
||||||
result <- &SASLResult{true, errors.New("no SASL capability " + e.Arguments[2])}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if e.Arguments[1] == "ACK" {
|
|
||||||
if irc.SASLMech != "PLAIN" {
|
|
||||||
result <- &SASLResult{true, errors.New("only PLAIN is supported")}
|
|
||||||
}
|
|
||||||
irc.SendRaw("AUTHENTICATE " + irc.SASLMech)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
irc.AddCallback("AUTHENTICATE", func(e *Event) {
|
|
||||||
str := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s\x00%s\x00%s", irc.SASLLogin, irc.SASLLogin, irc.SASLPassword)))
|
|
||||||
irc.SendRaw("AUTHENTICATE " + str)
|
|
||||||
})
|
|
||||||
irc.AddCallback("901", func(e *Event) {
|
|
||||||
irc.SendRaw("CAP END")
|
|
||||||
irc.SendRaw("QUIT")
|
|
||||||
result <- &SASLResult{true, errors.New(e.Arguments[1])}
|
|
||||||
})
|
|
||||||
irc.AddCallback("902", func(e *Event) {
|
|
||||||
irc.SendRaw("CAP END")
|
|
||||||
irc.SendRaw("QUIT")
|
|
||||||
result <- &SASLResult{true, errors.New(e.Arguments[1])}
|
|
||||||
})
|
|
||||||
irc.AddCallback("903", func(e *Event) {
|
|
||||||
result <- &SASLResult{false, nil}
|
|
||||||
})
|
|
||||||
irc.AddCallback("904", func(e *Event) {
|
|
||||||
irc.SendRaw("CAP END")
|
|
||||||
irc.SendRaw("QUIT")
|
|
||||||
result <- &SASLResult{true, errors.New(e.Arguments[1])}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
76
vendor/github.com/42wim/go-ircevent/irc_struct.go
generated
vendored
76
vendor/github.com/42wim/go-ircevent/irc_struct.go
generated
vendored
@@ -1,76 +0,0 @@
|
|||||||
// Copyright 2009 Thomas Jager <mail@jager.no> All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package irc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Connection struct {
|
|
||||||
sync.Mutex
|
|
||||||
sync.WaitGroup
|
|
||||||
Debug bool
|
|
||||||
Error chan error
|
|
||||||
Password string
|
|
||||||
UseTLS bool
|
|
||||||
UseSASL bool
|
|
||||||
RequestCaps []string
|
|
||||||
AcknowledgedCaps []string
|
|
||||||
SASLLogin string
|
|
||||||
SASLPassword string
|
|
||||||
SASLMech string
|
|
||||||
TLSConfig *tls.Config
|
|
||||||
Version string
|
|
||||||
Timeout time.Duration
|
|
||||||
PingFreq time.Duration
|
|
||||||
KeepAlive time.Duration
|
|
||||||
Server string
|
|
||||||
|
|
||||||
socket net.Conn
|
|
||||||
pwrite chan string
|
|
||||||
end chan struct{}
|
|
||||||
|
|
||||||
nick string //The nickname we want.
|
|
||||||
nickcurrent string //The nickname we currently have.
|
|
||||||
user string
|
|
||||||
registered bool
|
|
||||||
events map[string]map[int]func(*Event)
|
|
||||||
|
|
||||||
QuitMessage string
|
|
||||||
lastMessage time.Time
|
|
||||||
|
|
||||||
VerboseCallbackHandler bool
|
|
||||||
Log *log.Logger
|
|
||||||
|
|
||||||
stopped bool
|
|
||||||
quit bool //User called Quit, do not reconnect.
|
|
||||||
}
|
|
||||||
|
|
||||||
// A struct to represent an event.
|
|
||||||
type Event struct {
|
|
||||||
Code string
|
|
||||||
Raw string
|
|
||||||
Nick string //<nick>
|
|
||||||
Host string //<nick>!<usr>@<host>
|
|
||||||
Source string //<host>
|
|
||||||
User string //<usr>
|
|
||||||
Arguments []string
|
|
||||||
Tags map[string]string
|
|
||||||
Connection *Connection
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the last message from Event arguments.
|
|
||||||
// This function leaves the arguments untouched and
|
|
||||||
// returns an empty string if there are none.
|
|
||||||
func (e *Event) Message() string {
|
|
||||||
if len(e.Arguments) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return e.Arguments[len(e.Arguments)-1]
|
|
||||||
}
|
|
||||||
14
vendor/github.com/42wim/go-ircevent/irc_test_fuzz.go
generated
vendored
14
vendor/github.com/42wim/go-ircevent/irc_test_fuzz.go
generated
vendored
@@ -1,14 +0,0 @@
|
|||||||
// +build gofuzz
|
|
||||||
|
|
||||||
package irc
|
|
||||||
|
|
||||||
func Fuzz(data []byte) int {
|
|
||||||
b := bytes.NewBuffer(data)
|
|
||||||
event, err := parseToEvent(b.String())
|
|
||||||
if err == nil {
|
|
||||||
irc := IRC("go-eventirc", "go-eventirc")
|
|
||||||
irc.RunCallbacks(event)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
5
vendor/github.com/BurntSushi/toml/.gitignore
generated
vendored
Normal file
5
vendor/github.com/BurntSushi/toml/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
TAGS
|
||||||
|
tags
|
||||||
|
.*.swp
|
||||||
|
tomlcheck/tomlcheck
|
||||||
|
toml.test
|
||||||
15
vendor/github.com/BurntSushi/toml/.travis.yml
generated
vendored
Normal file
15
vendor/github.com/BurntSushi/toml/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.1
|
||||||
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
- 1.4
|
||||||
|
- 1.5
|
||||||
|
- 1.6
|
||||||
|
- tip
|
||||||
|
install:
|
||||||
|
- go install ./...
|
||||||
|
- go get github.com/BurntSushi/toml-test
|
||||||
|
script:
|
||||||
|
- export PATH="$PATH:$HOME/gopath/bin"
|
||||||
|
- make test
|
||||||
3
vendor/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
Normal file
3
vendor/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Compatible with TOML version
|
||||||
|
[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md)
|
||||||
|
|
||||||
19
vendor/github.com/BurntSushi/toml/Makefile
generated
vendored
Normal file
19
vendor/github.com/BurntSushi/toml/Makefile
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
install:
|
||||||
|
go install ./...
|
||||||
|
|
||||||
|
test: install
|
||||||
|
go test -v
|
||||||
|
toml-test toml-test-decoder
|
||||||
|
toml-test -encoder toml-test-encoder
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
gofmt -w *.go */*.go
|
||||||
|
colcheck *.go */*.go
|
||||||
|
|
||||||
|
tags:
|
||||||
|
find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS
|
||||||
|
|
||||||
|
push:
|
||||||
|
git push origin master
|
||||||
|
git push github master
|
||||||
|
|
||||||
218
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
Normal file
218
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
## TOML parser and encoder for Go with reflection
|
||||||
|
|
||||||
|
TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
|
||||||
|
reflection interface similar to Go's standard library `json` and `xml`
|
||||||
|
packages. This package also supports the `encoding.TextUnmarshaler` and
|
||||||
|
`encoding.TextMarshaler` interfaces so that you can define custom data
|
||||||
|
representations. (There is an example of this below.)
|
||||||
|
|
||||||
|
Spec: https://github.com/toml-lang/toml
|
||||||
|
|
||||||
|
Compatible with TOML version
|
||||||
|
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md)
|
||||||
|
|
||||||
|
Documentation: https://godoc.org/github.com/BurntSushi/toml
|
||||||
|
|
||||||
|
Installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get github.com/BurntSushi/toml
|
||||||
|
```
|
||||||
|
|
||||||
|
Try the toml validator:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get github.com/BurntSushi/toml/cmd/tomlv
|
||||||
|
tomlv some-toml-file.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
[](https://travis-ci.org/BurntSushi/toml) [](https://godoc.org/github.com/BurntSushi/toml)
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
This package passes all tests in
|
||||||
|
[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder
|
||||||
|
and the encoder.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
This package works similarly to how the Go standard library handles `XML`
|
||||||
|
and `JSON`. Namely, data is loaded into Go values via reflection.
|
||||||
|
|
||||||
|
For the simplest example, consider some TOML file as just a list of keys
|
||||||
|
and values:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
Age = 25
|
||||||
|
Cats = [ "Cauchy", "Plato" ]
|
||||||
|
Pi = 3.14
|
||||||
|
Perfection = [ 6, 28, 496, 8128 ]
|
||||||
|
DOB = 1987-07-05T05:45:00Z
|
||||||
|
```
|
||||||
|
|
||||||
|
Which could be defined in Go as:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Config struct {
|
||||||
|
Age int
|
||||||
|
Cats []string
|
||||||
|
Pi float64
|
||||||
|
Perfection []int
|
||||||
|
DOB time.Time // requires `import time`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And then decoded with:
|
||||||
|
|
||||||
|
```go
|
||||||
|
var conf Config
|
||||||
|
if _, err := toml.Decode(tomlData, &conf); err != nil {
|
||||||
|
// handle error
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use struct tags if your struct field name doesn't map to a TOML
|
||||||
|
key value directly:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
some_key_NAME = "wat"
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
type TOML struct {
|
||||||
|
ObscureKey string `toml:"some_key_NAME"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using the `encoding.TextUnmarshaler` interface
|
||||||
|
|
||||||
|
Here's an example that automatically parses duration strings into
|
||||||
|
`time.Duration` values:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[song]]
|
||||||
|
name = "Thunder Road"
|
||||||
|
duration = "4m49s"
|
||||||
|
|
||||||
|
[[song]]
|
||||||
|
name = "Stairway to Heaven"
|
||||||
|
duration = "8m03s"
|
||||||
|
```
|
||||||
|
|
||||||
|
Which can be decoded with:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type song struct {
|
||||||
|
Name string
|
||||||
|
Duration duration
|
||||||
|
}
|
||||||
|
type songs struct {
|
||||||
|
Song []song
|
||||||
|
}
|
||||||
|
var favorites songs
|
||||||
|
if _, err := toml.Decode(blob, &favorites); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range favorites.Song {
|
||||||
|
fmt.Printf("%s (%s)\n", s.Name, s.Duration)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And you'll also need a `duration` type that satisfies the
|
||||||
|
`encoding.TextUnmarshaler` interface:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type duration struct {
|
||||||
|
time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *duration) UnmarshalText(text []byte) error {
|
||||||
|
var err error
|
||||||
|
d.Duration, err = time.ParseDuration(string(text))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### More complex usage
|
||||||
|
|
||||||
|
Here's an example of how to load the example from the official spec page:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# This is a TOML document. Boom.
|
||||||
|
|
||||||
|
title = "TOML Example"
|
||||||
|
|
||||||
|
[owner]
|
||||||
|
name = "Tom Preston-Werner"
|
||||||
|
organization = "GitHub"
|
||||||
|
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
|
||||||
|
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
|
||||||
|
|
||||||
|
[database]
|
||||||
|
server = "192.168.1.1"
|
||||||
|
ports = [ 8001, 8001, 8002 ]
|
||||||
|
connection_max = 5000
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
[servers]
|
||||||
|
|
||||||
|
# You can indent as you please. Tabs or spaces. TOML don't care.
|
||||||
|
[servers.alpha]
|
||||||
|
ip = "10.0.0.1"
|
||||||
|
dc = "eqdc10"
|
||||||
|
|
||||||
|
[servers.beta]
|
||||||
|
ip = "10.0.0.2"
|
||||||
|
dc = "eqdc10"
|
||||||
|
|
||||||
|
[clients]
|
||||||
|
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
|
||||||
|
|
||||||
|
# Line breaks are OK when inside arrays
|
||||||
|
hosts = [
|
||||||
|
"alpha",
|
||||||
|
"omega"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
And the corresponding Go types are:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type tomlConfig struct {
|
||||||
|
Title string
|
||||||
|
Owner ownerInfo
|
||||||
|
DB database `toml:"database"`
|
||||||
|
Servers map[string]server
|
||||||
|
Clients clients
|
||||||
|
}
|
||||||
|
|
||||||
|
type ownerInfo struct {
|
||||||
|
Name string
|
||||||
|
Org string `toml:"organization"`
|
||||||
|
Bio string
|
||||||
|
DOB time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type database struct {
|
||||||
|
Server string
|
||||||
|
Ports []int
|
||||||
|
ConnMax int `toml:"connection_max"`
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type server struct {
|
||||||
|
IP string
|
||||||
|
DC string
|
||||||
|
}
|
||||||
|
|
||||||
|
type clients struct {
|
||||||
|
Data [][]interface{}
|
||||||
|
Hosts []string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that a case insensitive match will be tried if an exact match can't be
|
||||||
|
found.
|
||||||
|
|
||||||
|
A working example of the above can be found in `_examples/example.{go,toml}`.
|
||||||
90
vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go
generated
vendored
90
vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go
generated
vendored
@@ -1,90 +0,0 @@
|
|||||||
// Command toml-test-decoder satisfies the toml-test interface for testing
|
|
||||||
// TOML decoders. Namely, it accepts TOML on stdin and outputs JSON on stdout.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.SetFlags(0)
|
|
||||||
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
func usage() {
|
|
||||||
log.Printf("Usage: %s < toml-file\n", path.Base(os.Args[0]))
|
|
||||||
flag.PrintDefaults()
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if flag.NArg() != 0 {
|
|
||||||
flag.Usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
var tmp interface{}
|
|
||||||
if _, err := toml.DecodeReader(os.Stdin, &tmp); err != nil {
|
|
||||||
log.Fatalf("Error decoding TOML: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
typedTmp := translate(tmp)
|
|
||||||
if err := json.NewEncoder(os.Stdout).Encode(typedTmp); err != nil {
|
|
||||||
log.Fatalf("Error encoding JSON: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func translate(tomlData interface{}) interface{} {
|
|
||||||
switch orig := tomlData.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
typed := make(map[string]interface{}, len(orig))
|
|
||||||
for k, v := range orig {
|
|
||||||
typed[k] = translate(v)
|
|
||||||
}
|
|
||||||
return typed
|
|
||||||
case []map[string]interface{}:
|
|
||||||
typed := make([]map[string]interface{}, len(orig))
|
|
||||||
for i, v := range orig {
|
|
||||||
typed[i] = translate(v).(map[string]interface{})
|
|
||||||
}
|
|
||||||
return typed
|
|
||||||
case []interface{}:
|
|
||||||
typed := make([]interface{}, len(orig))
|
|
||||||
for i, v := range orig {
|
|
||||||
typed[i] = translate(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't really need to tag arrays, but let's be future proof.
|
|
||||||
// (If TOML ever supports tuples, we'll need this.)
|
|
||||||
return tag("array", typed)
|
|
||||||
case time.Time:
|
|
||||||
return tag("datetime", orig.Format("2006-01-02T15:04:05Z"))
|
|
||||||
case bool:
|
|
||||||
return tag("bool", fmt.Sprintf("%v", orig))
|
|
||||||
case int64:
|
|
||||||
return tag("integer", fmt.Sprintf("%d", orig))
|
|
||||||
case float64:
|
|
||||||
return tag("float", fmt.Sprintf("%v", orig))
|
|
||||||
case string:
|
|
||||||
return tag("string", orig)
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(fmt.Sprintf("Unknown type: %T", tomlData))
|
|
||||||
}
|
|
||||||
|
|
||||||
func tag(typeName string, data interface{}) map[string]interface{} {
|
|
||||||
return map[string]interface{}{
|
|
||||||
"type": typeName,
|
|
||||||
"value": data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
131
vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go
generated
vendored
131
vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go
generated
vendored
@@ -1,131 +0,0 @@
|
|||||||
// Command toml-test-encoder satisfies the toml-test interface for testing
|
|
||||||
// TOML encoders. Namely, it accepts JSON on stdin and outputs TOML on stdout.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.SetFlags(0)
|
|
||||||
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
func usage() {
|
|
||||||
log.Printf("Usage: %s < json-file\n", path.Base(os.Args[0]))
|
|
||||||
flag.PrintDefaults()
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if flag.NArg() != 0 {
|
|
||||||
flag.Usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
var tmp interface{}
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&tmp); err != nil {
|
|
||||||
log.Fatalf("Error decoding JSON: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tomlData := translate(tmp)
|
|
||||||
if err := toml.NewEncoder(os.Stdout).Encode(tomlData); err != nil {
|
|
||||||
log.Fatalf("Error encoding TOML: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func translate(typedJson interface{}) interface{} {
|
|
||||||
switch v := typedJson.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
if len(v) == 2 && in("type", v) && in("value", v) {
|
|
||||||
return untag(v)
|
|
||||||
}
|
|
||||||
m := make(map[string]interface{}, len(v))
|
|
||||||
for k, v2 := range v {
|
|
||||||
m[k] = translate(v2)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
case []interface{}:
|
|
||||||
tabArray := make([]map[string]interface{}, len(v))
|
|
||||||
for i := range v {
|
|
||||||
if m, ok := translate(v[i]).(map[string]interface{}); ok {
|
|
||||||
tabArray[i] = m
|
|
||||||
} else {
|
|
||||||
log.Fatalf("JSON arrays may only contain objects. This " +
|
|
||||||
"corresponds to only tables being allowed in " +
|
|
||||||
"TOML table arrays.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tabArray
|
|
||||||
}
|
|
||||||
log.Fatalf("Unrecognized JSON format '%T'.", typedJson)
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
func untag(typed map[string]interface{}) interface{} {
|
|
||||||
t := typed["type"].(string)
|
|
||||||
v := typed["value"]
|
|
||||||
switch t {
|
|
||||||
case "string":
|
|
||||||
return v.(string)
|
|
||||||
case "integer":
|
|
||||||
v := v.(string)
|
|
||||||
n, err := strconv.Atoi(v)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Could not parse '%s' as integer: %s", v, err)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
case "float":
|
|
||||||
v := v.(string)
|
|
||||||
f, err := strconv.ParseFloat(v, 64)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Could not parse '%s' as float64: %s", v, err)
|
|
||||||
}
|
|
||||||
return f
|
|
||||||
case "datetime":
|
|
||||||
v := v.(string)
|
|
||||||
t, err := time.Parse("2006-01-02T15:04:05Z", v)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Could not parse '%s' as a datetime: %s", v, err)
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
case "bool":
|
|
||||||
v := v.(string)
|
|
||||||
switch v {
|
|
||||||
case "true":
|
|
||||||
return true
|
|
||||||
case "false":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
log.Fatalf("Could not parse '%s' as a boolean.", v)
|
|
||||||
case "array":
|
|
||||||
v := v.([]interface{})
|
|
||||||
array := make([]interface{}, len(v))
|
|
||||||
for i := range v {
|
|
||||||
if m, ok := v[i].(map[string]interface{}); ok {
|
|
||||||
array[i] = untag(m)
|
|
||||||
} else {
|
|
||||||
log.Fatalf("Arrays may only contain other arrays or "+
|
|
||||||
"primitive values, but found a '%T'.", m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return array
|
|
||||||
}
|
|
||||||
log.Fatalf("Unrecognized tag type '%s'.", t)
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
func in(key string, m map[string]interface{}) bool {
|
|
||||||
_, ok := m[key]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
61
vendor/github.com/BurntSushi/toml/cmd/tomlv/main.go
generated
vendored
61
vendor/github.com/BurntSushi/toml/cmd/tomlv/main.go
generated
vendored
@@ -1,61 +0,0 @@
|
|||||||
// Command tomlv validates TOML documents and prints each key's type.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
flagTypes = false
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.SetFlags(0)
|
|
||||||
|
|
||||||
flag.BoolVar(&flagTypes, "types", flagTypes,
|
|
||||||
"When set, the types of every defined key will be shown.")
|
|
||||||
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
func usage() {
|
|
||||||
log.Printf("Usage: %s toml-file [ toml-file ... ]\n",
|
|
||||||
path.Base(os.Args[0]))
|
|
||||||
flag.PrintDefaults()
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if flag.NArg() < 1 {
|
|
||||||
flag.Usage()
|
|
||||||
}
|
|
||||||
for _, f := range flag.Args() {
|
|
||||||
var tmp interface{}
|
|
||||||
md, err := toml.DecodeFile(f, &tmp)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error in '%s': %s", f, err)
|
|
||||||
}
|
|
||||||
if flagTypes {
|
|
||||||
printTypes(md)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printTypes(md toml.MetaData) {
|
|
||||||
tabw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
||||||
for _, key := range md.Keys() {
|
|
||||||
fmt.Fprintf(tabw, "%s%s\t%s\n",
|
|
||||||
strings.Repeat(" ", len(key)-1), key, md.Type(key...))
|
|
||||||
}
|
|
||||||
tabw.Flush()
|
|
||||||
}
|
|
||||||
1
vendor/github.com/BurntSushi/toml/session.vim
generated
vendored
Normal file
1
vendor/github.com/BurntSushi/toml/session.vim
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
au BufWritePost *.go silent!make tags > /dev/null 2>&1
|
||||||
138
vendor/github.com/GeertJohan/go.rice/appended.go
generated
vendored
138
vendor/github.com/GeertJohan/go.rice/appended.go
generated
vendored
@@ -1,138 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/zip"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/daaku/go.zipexe"
|
|
||||||
"github.com/kardianos/osext"
|
|
||||||
)
|
|
||||||
|
|
||||||
// appendedBox defines an appended box
|
|
||||||
type appendedBox struct {
|
|
||||||
Name string // box name
|
|
||||||
Files map[string]*appendedFile // appended files (*zip.File) by full path
|
|
||||||
}
|
|
||||||
|
|
||||||
type appendedFile struct {
|
|
||||||
zipFile *zip.File
|
|
||||||
dir bool
|
|
||||||
dirInfo *appendedDirInfo
|
|
||||||
children []*appendedFile
|
|
||||||
content []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// appendedBoxes is a public register of appendes boxes
|
|
||||||
var appendedBoxes = make(map[string]*appendedBox)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// find if exec is appended
|
|
||||||
thisFile, err := osext.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return // not appended or cant find self executable
|
|
||||||
}
|
|
||||||
closer, rd, err := zipexe.OpenCloser(thisFile)
|
|
||||||
if err != nil {
|
|
||||||
return // not appended
|
|
||||||
}
|
|
||||||
defer closer.Close()
|
|
||||||
|
|
||||||
for _, f := range rd.File {
|
|
||||||
// get box and file name from f.Name
|
|
||||||
fileParts := strings.SplitN(strings.TrimLeft(filepath.ToSlash(f.Name), "/"), "/", 2)
|
|
||||||
boxName := fileParts[0]
|
|
||||||
var fileName string
|
|
||||||
if len(fileParts) > 1 {
|
|
||||||
fileName = fileParts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// find box or create new one if doesn't exist
|
|
||||||
box := appendedBoxes[boxName]
|
|
||||||
if box == nil {
|
|
||||||
box = &appendedBox{
|
|
||||||
Name: boxName,
|
|
||||||
Files: make(map[string]*appendedFile),
|
|
||||||
}
|
|
||||||
appendedBoxes[boxName] = box
|
|
||||||
}
|
|
||||||
|
|
||||||
// create and add file to box
|
|
||||||
af := &appendedFile{
|
|
||||||
zipFile: f,
|
|
||||||
}
|
|
||||||
if f.Comment == "dir" {
|
|
||||||
af.dir = true
|
|
||||||
af.dirInfo = &appendedDirInfo{
|
|
||||||
name: filepath.Base(af.zipFile.Name),
|
|
||||||
//++ TODO: use zip modtime when that is set correctly: af.zipFile.ModTime()
|
|
||||||
time: time.Now(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// this is a file, we need it's contents so we can create a bytes.Reader when the file is opened
|
|
||||||
// make a new byteslice
|
|
||||||
af.content = make([]byte, af.zipFile.FileInfo().Size())
|
|
||||||
// ignore reading empty files from zip (empty file still is a valid file to be read though!)
|
|
||||||
if len(af.content) > 0 {
|
|
||||||
// open io.ReadCloser
|
|
||||||
rc, err := af.zipFile.Open()
|
|
||||||
if err != nil {
|
|
||||||
af.content = nil // this will cause an error when the file is being opened or seeked (which is good)
|
|
||||||
// TODO: it's quite blunt to just log this stuff. but this is in init, so rice.Debug can't be changed yet..
|
|
||||||
log.Printf("error opening appended file %s: %v", af.zipFile.Name, err)
|
|
||||||
} else {
|
|
||||||
_, err = rc.Read(af.content)
|
|
||||||
rc.Close()
|
|
||||||
if err != nil {
|
|
||||||
af.content = nil // this will cause an error when the file is being opened or seeked (which is good)
|
|
||||||
// TODO: it's quite blunt to just log this stuff. but this is in init, so rice.Debug can't be changed yet..
|
|
||||||
log.Printf("error reading data for appended file %s: %v", af.zipFile.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add appendedFile to box file list
|
|
||||||
box.Files[fileName] = af
|
|
||||||
|
|
||||||
// add to parent dir (if any)
|
|
||||||
dirName := filepath.Dir(fileName)
|
|
||||||
if dirName == "." {
|
|
||||||
dirName = ""
|
|
||||||
}
|
|
||||||
if fileName != "" { // don't make box root dir a child of itself
|
|
||||||
if dir := box.Files[dirName]; dir != nil {
|
|
||||||
dir.children = append(dir.children, af)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// implements os.FileInfo.
|
|
||||||
// used for Readdir()
|
|
||||||
type appendedDirInfo struct {
|
|
||||||
name string
|
|
||||||
time time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (adi *appendedDirInfo) Name() string {
|
|
||||||
return adi.name
|
|
||||||
}
|
|
||||||
func (adi *appendedDirInfo) Size() int64 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
func (adi *appendedDirInfo) Mode() os.FileMode {
|
|
||||||
return os.ModeDir
|
|
||||||
}
|
|
||||||
func (adi *appendedDirInfo) ModTime() time.Time {
|
|
||||||
return adi.time
|
|
||||||
}
|
|
||||||
func (adi *appendedDirInfo) IsDir() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
func (adi *appendedDirInfo) Sys() interface{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
337
vendor/github.com/GeertJohan/go.rice/box.go
generated
vendored
337
vendor/github.com/GeertJohan/go.rice/box.go
generated
vendored
@@ -1,337 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/GeertJohan/go.rice/embedded"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Box abstracts a directory for resources/files.
|
|
||||||
// It can either load files from disk, or from embedded code (when `rice --embed` was ran).
|
|
||||||
type Box struct {
|
|
||||||
name string
|
|
||||||
absolutePath string
|
|
||||||
embed *embedded.EmbeddedBox
|
|
||||||
appendd *appendedBox
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultLocateOrder = []LocateMethod{LocateEmbedded, LocateAppended, LocateFS}
|
|
||||||
|
|
||||||
func findBox(name string, order []LocateMethod) (*Box, error) {
|
|
||||||
b := &Box{name: name}
|
|
||||||
|
|
||||||
// no support for absolute paths since gopath can be different on different machines.
|
|
||||||
// therefore, required box must be located relative to package requiring it.
|
|
||||||
if filepath.IsAbs(name) {
|
|
||||||
return nil, errors.New("given name/path is absolute")
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
for _, method := range order {
|
|
||||||
switch method {
|
|
||||||
case LocateEmbedded:
|
|
||||||
if embed := embedded.EmbeddedBoxes[name]; embed != nil {
|
|
||||||
b.embed = embed
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
case LocateAppended:
|
|
||||||
appendedBoxName := strings.Replace(name, `/`, `-`, -1)
|
|
||||||
if appendd := appendedBoxes[appendedBoxName]; appendd != nil {
|
|
||||||
b.appendd = appendd
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
case LocateFS:
|
|
||||||
// resolve absolute directory path
|
|
||||||
err := b.resolveAbsolutePathFromCaller()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// check if absolutePath exists on filesystem
|
|
||||||
info, err := os.Stat(b.absolutePath)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// check if absolutePath is actually a directory
|
|
||||||
if !info.IsDir() {
|
|
||||||
err = errors.New("given name/path is not a directory")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
case LocateWorkingDirectory:
|
|
||||||
// resolve absolute directory path
|
|
||||||
err := b.resolveAbsolutePathFromWorkingDirectory()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// check if absolutePath exists on filesystem
|
|
||||||
info, err := os.Stat(b.absolutePath)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// check if absolutePath is actually a directory
|
|
||||||
if !info.IsDir() {
|
|
||||||
err = errors.New("given name/path is not a directory")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
err = fmt.Errorf("could not locate box %q", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindBox returns a Box instance for given name.
|
|
||||||
// When the given name is a relative path, it's base path will be the calling pkg/cmd's source root.
|
|
||||||
// When the given name is absolute, it's absolute. derp.
|
|
||||||
// Make sure the path doesn't contain any sensitive information as it might be placed into generated go source (embedded).
|
|
||||||
func FindBox(name string) (*Box, error) {
|
|
||||||
return findBox(name, defaultLocateOrder)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustFindBox returns a Box instance for given name, like FindBox does.
|
|
||||||
// It does not return an error, instead it panics when an error occurs.
|
|
||||||
func MustFindBox(name string) *Box {
|
|
||||||
box, err := findBox(name, defaultLocateOrder)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is injected as a mutable function literal so that we can mock it out in
|
|
||||||
// tests and return a fixed test file.
|
|
||||||
var resolveAbsolutePathFromCaller = func(name string, nStackFrames int) (string, error) {
|
|
||||||
_, callingGoFile, _, ok := runtime.Caller(nStackFrames)
|
|
||||||
if !ok {
|
|
||||||
return "", errors.New("couldn't find caller on stack")
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve to proper path
|
|
||||||
pkgDir := filepath.Dir(callingGoFile)
|
|
||||||
// fix for go cover
|
|
||||||
const coverPath = "_test/_obj_test"
|
|
||||||
if !filepath.IsAbs(pkgDir) {
|
|
||||||
if i := strings.Index(pkgDir, coverPath); i >= 0 {
|
|
||||||
pkgDir = pkgDir[:i] + pkgDir[i+len(coverPath):] // remove coverPath
|
|
||||||
pkgDir = filepath.Join(os.Getenv("GOPATH"), "src", pkgDir) // make absolute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filepath.Join(pkgDir, name), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) resolveAbsolutePathFromCaller() error {
|
|
||||||
path, err := resolveAbsolutePathFromCaller(b.name, 4)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.absolutePath = path
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) resolveAbsolutePathFromWorkingDirectory() error {
|
|
||||||
path, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.absolutePath = filepath.Join(path, b.name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmbedded indicates wether this box was embedded into the application
|
|
||||||
func (b *Box) IsEmbedded() bool {
|
|
||||||
return b.embed != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAppended indicates wether this box was appended to the application
|
|
||||||
func (b *Box) IsAppended() bool {
|
|
||||||
return b.appendd != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time returns how actual the box is.
|
|
||||||
// When the box is embedded, it's value is saved in the embedding code.
|
|
||||||
// When the box is live, this methods returns time.Now()
|
|
||||||
func (b *Box) Time() time.Time {
|
|
||||||
if b.IsEmbedded() {
|
|
||||||
return b.embed.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
//++ TODO: return time for appended box
|
|
||||||
|
|
||||||
return time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open opens a File from the box
|
|
||||||
// If there is an error, it will be of type *os.PathError.
|
|
||||||
func (b *Box) Open(name string) (*File, error) {
|
|
||||||
if Debug {
|
|
||||||
fmt.Printf("Open(%s)\n", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.IsEmbedded() {
|
|
||||||
if Debug {
|
|
||||||
fmt.Println("Box is embedded")
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim prefix (paths are relative to box)
|
|
||||||
name = strings.TrimLeft(name, "/")
|
|
||||||
if Debug {
|
|
||||||
fmt.Printf("Trying %s\n", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for file
|
|
||||||
ef := b.embed.Files[name]
|
|
||||||
if ef == nil {
|
|
||||||
if Debug {
|
|
||||||
fmt.Println("Didn't find file in embed")
|
|
||||||
}
|
|
||||||
// file not found, try dir
|
|
||||||
ed := b.embed.Dirs[name]
|
|
||||||
if ed == nil {
|
|
||||||
if Debug {
|
|
||||||
fmt.Println("Didn't find dir in embed")
|
|
||||||
}
|
|
||||||
// dir not found, error out
|
|
||||||
return nil, &os.PathError{
|
|
||||||
Op: "open",
|
|
||||||
Path: name,
|
|
||||||
Err: os.ErrNotExist,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if Debug {
|
|
||||||
fmt.Println("Found dir. Returning virtual dir")
|
|
||||||
}
|
|
||||||
vd := newVirtualDir(ed)
|
|
||||||
return &File{virtualD: vd}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// box is embedded
|
|
||||||
if Debug {
|
|
||||||
fmt.Println("Found file. Returning virtual file")
|
|
||||||
}
|
|
||||||
vf := newVirtualFile(ef)
|
|
||||||
return &File{virtualF: vf}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.IsAppended() {
|
|
||||||
// trim prefix (paths are relative to box)
|
|
||||||
name = strings.TrimLeft(name, "/")
|
|
||||||
|
|
||||||
// search for file
|
|
||||||
appendedFile := b.appendd.Files[name]
|
|
||||||
if appendedFile == nil {
|
|
||||||
return nil, &os.PathError{
|
|
||||||
Op: "open",
|
|
||||||
Path: name,
|
|
||||||
Err: os.ErrNotExist,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new file
|
|
||||||
f := &File{
|
|
||||||
appendedF: appendedFile,
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this file is a directory, we want to be able to read and seek
|
|
||||||
if !appendedFile.dir {
|
|
||||||
// looks like malformed data in zip, error now
|
|
||||||
if appendedFile.content == nil {
|
|
||||||
return nil, &os.PathError{
|
|
||||||
Op: "open",
|
|
||||||
Path: "name",
|
|
||||||
Err: errors.New("error reading data from zip file"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// create new bytes.Reader
|
|
||||||
f.appendedFileReader = bytes.NewReader(appendedFile.content)
|
|
||||||
}
|
|
||||||
|
|
||||||
// all done
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform os open
|
|
||||||
if Debug {
|
|
||||||
fmt.Printf("Using os.Open(%s)", filepath.Join(b.absolutePath, name))
|
|
||||||
}
|
|
||||||
file, err := os.Open(filepath.Join(b.absolutePath, name))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &File{realF: file}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns the content of the file with given name as []byte.
|
|
||||||
func (b *Box) Bytes(name string) ([]byte, error) {
|
|
||||||
file, err := b.Open(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
content, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return content, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustBytes returns the content of the file with given name as []byte.
|
|
||||||
// panic's on error.
|
|
||||||
func (b *Box) MustBytes(name string) []byte {
|
|
||||||
bts, err := b.Bytes(name)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return bts
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the content of the file with given name as string.
|
|
||||||
func (b *Box) String(name string) (string, error) {
|
|
||||||
// check if box is embedded, optimized fast path
|
|
||||||
if b.IsEmbedded() {
|
|
||||||
// find file in embed
|
|
||||||
ef := b.embed.Files[name]
|
|
||||||
if ef == nil {
|
|
||||||
return "", os.ErrNotExist
|
|
||||||
}
|
|
||||||
// return as string
|
|
||||||
return ef.Content, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
bts, err := b.Bytes(name)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(bts), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustString returns the content of the file with given name as string.
|
|
||||||
// panic's on error.
|
|
||||||
func (b *Box) MustString(name string) string {
|
|
||||||
str, err := b.String(name)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the name of the box
|
|
||||||
func (b *Box) Name() string {
|
|
||||||
return b.name
|
|
||||||
}
|
|
||||||
39
vendor/github.com/GeertJohan/go.rice/config.go
generated
vendored
39
vendor/github.com/GeertJohan/go.rice/config.go
generated
vendored
@@ -1,39 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
// LocateMethod defines how a box is located.
|
|
||||||
type LocateMethod int
|
|
||||||
|
|
||||||
const (
|
|
||||||
LocateFS = LocateMethod(iota) // Locate on the filesystem according to package path.
|
|
||||||
LocateAppended // Locate boxes appended to the executable.
|
|
||||||
LocateEmbedded // Locate embedded boxes.
|
|
||||||
LocateWorkingDirectory // Locate on the binary working directory
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config allows customizing the box lookup behavior.
|
|
||||||
type Config struct {
|
|
||||||
// LocateOrder defines the priority order that boxes are searched for. By
|
|
||||||
// default, the package global FindBox searches for embedded boxes first,
|
|
||||||
// then appended boxes, and then finally boxes on the filesystem. That
|
|
||||||
// search order may be customized by provided the ordered list here. Leaving
|
|
||||||
// out a particular method will omit that from the search space. For
|
|
||||||
// example, []LocateMethod{LocateEmbedded, LocateAppended} will never search
|
|
||||||
// the filesystem for boxes.
|
|
||||||
LocateOrder []LocateMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindBox searches for boxes using the LocateOrder of the config.
|
|
||||||
func (c *Config) FindBox(boxName string) (*Box, error) {
|
|
||||||
return findBox(boxName, c.LocateOrder)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustFindBox searches for boxes using the LocateOrder of the config, like
|
|
||||||
// FindBox does. It does not return an error, instead it panics when an error
|
|
||||||
// occurs.
|
|
||||||
func (c *Config) MustFindBox(boxName string) *Box {
|
|
||||||
box, err := findBox(boxName, c.LocateOrder)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
4
vendor/github.com/GeertJohan/go.rice/debug.go
generated
vendored
4
vendor/github.com/GeertJohan/go.rice/debug.go
generated
vendored
@@ -1,4 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
// Debug can be set to true to enable debugging.
|
|
||||||
var Debug = false
|
|
||||||
90
vendor/github.com/GeertJohan/go.rice/embedded.go
generated
vendored
90
vendor/github.com/GeertJohan/go.rice/embedded.go
generated
vendored
@@ -1,90 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/GeertJohan/go.rice/embedded"
|
|
||||||
)
|
|
||||||
|
|
||||||
// re-type to make exported methods invisible to user (godoc)
|
|
||||||
// they're not required for the user
|
|
||||||
// embeddedDirInfo implements os.FileInfo
|
|
||||||
type embeddedDirInfo embedded.EmbeddedDir
|
|
||||||
|
|
||||||
// Name returns the base name of the directory
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ed *embeddedDirInfo) Name() string {
|
|
||||||
return ed.Filename
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size always returns 0
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ed *embeddedDirInfo) Size() int64 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode returns the file mode bits
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ed *embeddedDirInfo) Mode() os.FileMode {
|
|
||||||
return os.FileMode(0555 | os.ModeDir) // dr-xr-xr-x
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModTime returns the modification time
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ed *embeddedDirInfo) ModTime() time.Time {
|
|
||||||
return ed.DirModTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDir returns the abbreviation for Mode().IsDir() (always true)
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ed *embeddedDirInfo) IsDir() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sys returns the underlying data source (always nil)
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ed *embeddedDirInfo) Sys() interface{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-type to make exported methods invisible to user (godoc)
|
|
||||||
// they're not required for the user
|
|
||||||
// embeddedFileInfo implements os.FileInfo
|
|
||||||
type embeddedFileInfo embedded.EmbeddedFile
|
|
||||||
|
|
||||||
// Name returns the base name of the file
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ef *embeddedFileInfo) Name() string {
|
|
||||||
return ef.Filename
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the length in bytes for regular files; system-dependent for others
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ef *embeddedFileInfo) Size() int64 {
|
|
||||||
return int64(len(ef.Content))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode returns the file mode bits
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ef *embeddedFileInfo) Mode() os.FileMode {
|
|
||||||
return os.FileMode(0555) // r-xr-xr-x
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModTime returns the modification time
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ef *embeddedFileInfo) ModTime() time.Time {
|
|
||||||
return ef.FileModTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDir returns the abbreviation for Mode().IsDir() (always false)
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ef *embeddedFileInfo) IsDir() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sys returns the underlying data source (always nil)
|
|
||||||
// (implementing os.FileInfo)
|
|
||||||
func (ef *embeddedFileInfo) Sys() interface{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
80
vendor/github.com/GeertJohan/go.rice/embedded/embedded.go
generated
vendored
80
vendor/github.com/GeertJohan/go.rice/embedded/embedded.go
generated
vendored
@@ -1,80 +0,0 @@
|
|||||||
// Package embedded defines embedded data types that are shared between the go.rice package and generated code.
|
|
||||||
package embedded
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
EmbedTypeGo = 0
|
|
||||||
EmbedTypeSyso = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// EmbeddedBox defines an embedded box
|
|
||||||
type EmbeddedBox struct {
|
|
||||||
Name string // box name
|
|
||||||
Time time.Time // embed time
|
|
||||||
EmbedType int // kind of embedding
|
|
||||||
Files map[string]*EmbeddedFile // ALL embedded files by full path
|
|
||||||
Dirs map[string]*EmbeddedDir // ALL embedded dirs by full path
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link creates the ChildDirs and ChildFiles links in all EmbeddedDir's
|
|
||||||
func (e *EmbeddedBox) Link() {
|
|
||||||
for path, ed := range e.Dirs {
|
|
||||||
fmt.Println(path)
|
|
||||||
ed.ChildDirs = make([]*EmbeddedDir, 0)
|
|
||||||
ed.ChildFiles = make([]*EmbeddedFile, 0)
|
|
||||||
}
|
|
||||||
for path, ed := range e.Dirs {
|
|
||||||
parentDirpath, _ := filepath.Split(path)
|
|
||||||
if strings.HasSuffix(parentDirpath, "/") {
|
|
||||||
parentDirpath = parentDirpath[:len(parentDirpath)-1]
|
|
||||||
}
|
|
||||||
parentDir := e.Dirs[parentDirpath]
|
|
||||||
if parentDir == nil {
|
|
||||||
panic("parentDir `" + parentDirpath + "` is missing in embedded box")
|
|
||||||
}
|
|
||||||
parentDir.ChildDirs = append(parentDir.ChildDirs, ed)
|
|
||||||
}
|
|
||||||
for path, ef := range e.Files {
|
|
||||||
dirpath, _ := filepath.Split(path)
|
|
||||||
if strings.HasSuffix(dirpath, "/") {
|
|
||||||
dirpath = dirpath[:len(dirpath)-1]
|
|
||||||
}
|
|
||||||
dir := e.Dirs[dirpath]
|
|
||||||
if dir == nil {
|
|
||||||
panic("dir `" + dirpath + "` is missing in embedded box")
|
|
||||||
}
|
|
||||||
dir.ChildFiles = append(dir.ChildFiles, ef)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmbeddedDir is instanced in the code generated by the rice tool and contains all necicary information about an embedded file
|
|
||||||
type EmbeddedDir struct {
|
|
||||||
Filename string
|
|
||||||
DirModTime time.Time
|
|
||||||
ChildDirs []*EmbeddedDir // direct childs, as returned by virtualDir.Readdir()
|
|
||||||
ChildFiles []*EmbeddedFile // direct childs, as returned by virtualDir.Readdir()
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmbeddedFile is instanced in the code generated by the rice tool and contains all necicary information about an embedded file
|
|
||||||
type EmbeddedFile struct {
|
|
||||||
Filename string // filename
|
|
||||||
FileModTime time.Time
|
|
||||||
Content string
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmbeddedBoxes is a public register of embedded boxes
|
|
||||||
var EmbeddedBoxes = make(map[string]*EmbeddedBox)
|
|
||||||
|
|
||||||
// RegisterEmbeddedBox registers an EmbeddedBox
|
|
||||||
func RegisterEmbeddedBox(name string, box *EmbeddedBox) {
|
|
||||||
if _, exists := EmbeddedBoxes[name]; exists {
|
|
||||||
panic(fmt.Sprintf("EmbeddedBox with name `%s` exists already", name))
|
|
||||||
}
|
|
||||||
EmbeddedBoxes[name] = box
|
|
||||||
}
|
|
||||||
69
vendor/github.com/GeertJohan/go.rice/example/example.go
generated
vendored
69
vendor/github.com/GeertJohan/go.rice/example/example.go
generated
vendored
@@ -1,69 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/GeertJohan/go.rice"
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
conf := rice.Config{
|
|
||||||
LocateOrder: []rice.LocateMethod{rice.LocateEmbedded, rice.LocateAppended, rice.LocateFS},
|
|
||||||
}
|
|
||||||
box, err := conf.FindBox("example-files")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error opening rice.Box: %s\n", err)
|
|
||||||
}
|
|
||||||
// spew.Dump(box)
|
|
||||||
|
|
||||||
contentString, err := box.String("file.txt")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("could not read file contents as string: %s\n", err)
|
|
||||||
}
|
|
||||||
log.Printf("Read some file contents as string:\n%s\n", contentString)
|
|
||||||
|
|
||||||
contentBytes, err := box.Bytes("file.txt")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("could not read file contents as byteSlice: %s\n", err)
|
|
||||||
}
|
|
||||||
log.Printf("Read some file contents as byteSlice:\n%s\n", hex.Dump(contentBytes))
|
|
||||||
|
|
||||||
file, err := box.Open("file.txt")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("could not open file: %s\n", err)
|
|
||||||
}
|
|
||||||
spew.Dump(file)
|
|
||||||
|
|
||||||
// find/create a rice.Box
|
|
||||||
templateBox, err := rice.FindBox("example-templates")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
// get file contents as string
|
|
||||||
templateString, err := templateBox.String("message.tmpl")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
// parse and execute the template
|
|
||||||
tmplMessage, err := template.New("message").Parse(templateString)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
tmplMessage.Execute(os.Stdout, map[string]string{"Message": "Hello, world!"})
|
|
||||||
|
|
||||||
http.Handle("/", http.FileServer(box.HTTPBox()))
|
|
||||||
go func() {
|
|
||||||
fmt.Println("Serving files on :8080, press ctrl-C to exit")
|
|
||||||
err := http.ListenAndServe(":8080", nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error serving files: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
select {}
|
|
||||||
}
|
|
||||||
144
vendor/github.com/GeertJohan/go.rice/file.go
generated
vendored
144
vendor/github.com/GeertJohan/go.rice/file.go
generated
vendored
@@ -1,144 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// File implements the io.Reader, io.Seeker, io.Closer and http.File interfaces
|
|
||||||
type File struct {
|
|
||||||
// File abstracts file methods so the user doesn't see the difference between rice.virtualFile, rice.virtualDir and os.File
|
|
||||||
// TODO: maybe use internal File interface and four implementations: *os.File, appendedFile, virtualFile, virtualDir
|
|
||||||
|
|
||||||
// real file on disk
|
|
||||||
realF *os.File
|
|
||||||
|
|
||||||
// when embedded (go)
|
|
||||||
virtualF *virtualFile
|
|
||||||
virtualD *virtualDir
|
|
||||||
|
|
||||||
// when appended (zip)
|
|
||||||
appendedF *appendedFile
|
|
||||||
appendedFileReader *bytes.Reader
|
|
||||||
// TODO: is appendedFileReader subject of races? Might need a lock here..
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is like (*os.File).Close()
|
|
||||||
// Visit http://golang.org/pkg/os/#File.Close for more information
|
|
||||||
func (f *File) Close() error {
|
|
||||||
if f.appendedF != nil {
|
|
||||||
if f.appendedFileReader == nil {
|
|
||||||
return errors.New("already closed")
|
|
||||||
}
|
|
||||||
f.appendedFileReader = nil
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if f.virtualF != nil {
|
|
||||||
return f.virtualF.close()
|
|
||||||
}
|
|
||||||
if f.virtualD != nil {
|
|
||||||
return f.virtualD.close()
|
|
||||||
}
|
|
||||||
return f.realF.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stat is like (*os.File).Stat()
|
|
||||||
// Visit http://golang.org/pkg/os/#File.Stat for more information
|
|
||||||
func (f *File) Stat() (os.FileInfo, error) {
|
|
||||||
if f.appendedF != nil {
|
|
||||||
if f.appendedF.dir {
|
|
||||||
return f.appendedF.dirInfo, nil
|
|
||||||
}
|
|
||||||
if f.appendedFileReader == nil {
|
|
||||||
return nil, errors.New("file is closed")
|
|
||||||
}
|
|
||||||
return f.appendedF.zipFile.FileInfo(), nil
|
|
||||||
}
|
|
||||||
if f.virtualF != nil {
|
|
||||||
return f.virtualF.stat()
|
|
||||||
}
|
|
||||||
if f.virtualD != nil {
|
|
||||||
return f.virtualD.stat()
|
|
||||||
}
|
|
||||||
return f.realF.Stat()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Readdir is like (*os.File).Readdir()
|
|
||||||
// Visit http://golang.org/pkg/os/#File.Readdir for more information
|
|
||||||
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
|
||||||
if f.appendedF != nil {
|
|
||||||
if f.appendedF.dir {
|
|
||||||
fi := make([]os.FileInfo, 0, len(f.appendedF.children))
|
|
||||||
for _, childAppendedFile := range f.appendedF.children {
|
|
||||||
if childAppendedFile.dir {
|
|
||||||
fi = append(fi, childAppendedFile.dirInfo)
|
|
||||||
} else {
|
|
||||||
fi = append(fi, childAppendedFile.zipFile.FileInfo())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fi, nil
|
|
||||||
}
|
|
||||||
//++ TODO: is os.ErrInvalid the correct error for Readdir on file?
|
|
||||||
return nil, os.ErrInvalid
|
|
||||||
}
|
|
||||||
if f.virtualF != nil {
|
|
||||||
return f.virtualF.readdir(count)
|
|
||||||
}
|
|
||||||
if f.virtualD != nil {
|
|
||||||
return f.virtualD.readdir(count)
|
|
||||||
}
|
|
||||||
return f.realF.Readdir(count)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read is like (*os.File).Read()
|
|
||||||
// Visit http://golang.org/pkg/os/#File.Read for more information
|
|
||||||
func (f *File) Read(bts []byte) (int, error) {
|
|
||||||
if f.appendedF != nil {
|
|
||||||
if f.appendedFileReader == nil {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "read",
|
|
||||||
Path: filepath.Base(f.appendedF.zipFile.Name),
|
|
||||||
Err: errors.New("file is closed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if f.appendedF.dir {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "read",
|
|
||||||
Path: filepath.Base(f.appendedF.zipFile.Name),
|
|
||||||
Err: errors.New("is a directory"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return f.appendedFileReader.Read(bts)
|
|
||||||
}
|
|
||||||
if f.virtualF != nil {
|
|
||||||
return f.virtualF.read(bts)
|
|
||||||
}
|
|
||||||
if f.virtualD != nil {
|
|
||||||
return f.virtualD.read(bts)
|
|
||||||
}
|
|
||||||
return f.realF.Read(bts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek is like (*os.File).Seek()
|
|
||||||
// Visit http://golang.org/pkg/os/#File.Seek for more information
|
|
||||||
func (f *File) Seek(offset int64, whence int) (int64, error) {
|
|
||||||
if f.appendedF != nil {
|
|
||||||
if f.appendedFileReader == nil {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "seek",
|
|
||||||
Path: filepath.Base(f.appendedF.zipFile.Name),
|
|
||||||
Err: errors.New("file is closed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return f.appendedFileReader.Seek(offset, whence)
|
|
||||||
}
|
|
||||||
if f.virtualF != nil {
|
|
||||||
return f.virtualF.seek(offset, whence)
|
|
||||||
}
|
|
||||||
if f.virtualD != nil {
|
|
||||||
return f.virtualD.seek(offset, whence)
|
|
||||||
}
|
|
||||||
return f.realF.Seek(offset, whence)
|
|
||||||
}
|
|
||||||
21
vendor/github.com/GeertJohan/go.rice/http.go
generated
vendored
21
vendor/github.com/GeertJohan/go.rice/http.go
generated
vendored
@@ -1,21 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HTTPBox implements http.FileSystem which allows the use of Box with a http.FileServer.
|
|
||||||
// e.g.: http.Handle("/", http.FileServer(rice.MustFindBox("http-files").HTTPBox()))
|
|
||||||
type HTTPBox struct {
|
|
||||||
*Box
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPBox creates a new HTTPBox from an existing Box
|
|
||||||
func (b *Box) HTTPBox() *HTTPBox {
|
|
||||||
return &HTTPBox{b}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open returns a File using the http.File interface
|
|
||||||
func (hb *HTTPBox) Open(name string) (http.File, error) {
|
|
||||||
return hb.Box.Open(name)
|
|
||||||
}
|
|
||||||
172
vendor/github.com/GeertJohan/go.rice/rice/append.go
generated
vendored
172
vendor/github.com/GeertJohan/go.rice/rice/append.go
generated
vendored
@@ -1,172 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/zip"
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/daaku/go.zipexe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func operationAppend(pkgs []*build.Package) {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
_, err := exec.LookPath("zip")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("#### WARNING ! ####")
|
|
||||||
fmt.Println("`rice append` is known not to work under windows because the `zip` command is not available. Please let me know if you got this to work (and how).")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARKED FOR DELETION
|
|
||||||
// This is actually not required, the append command now has the option --exec required.
|
|
||||||
// // check if package is a command
|
|
||||||
// if !pkg.IsCommand() {
|
|
||||||
// fmt.Println("Error: can not append to non-main package. Please follow instructions at github.com/GeertJohan/go.rice")
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// create tmp zipfile
|
|
||||||
tmpZipfileName := filepath.Join(os.TempDir(), fmt.Sprintf("ricebox-%d-%s.zip", time.Now().Unix(), randomString(10)))
|
|
||||||
verbosef("Will create tmp zipfile: %s\n", tmpZipfileName)
|
|
||||||
tmpZipfile, err := os.Create(tmpZipfileName)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error creating tmp zipfile: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
tmpZipfile.Close()
|
|
||||||
os.Remove(tmpZipfileName)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// find abs path for binary file
|
|
||||||
binfileName, err := filepath.Abs(flags.Append.Executable)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error finding absolute path for executable to append: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
verbosef("Will append to file: %s\n", binfileName)
|
|
||||||
|
|
||||||
// check that command doesn't already have zip appended
|
|
||||||
if rd, _ := zipexe.Open(binfileName); rd != nil {
|
|
||||||
fmt.Printf("Cannot append to already appended executable. Please remove %s and build a fresh one.\n", binfileName)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// open binfile
|
|
||||||
binfile, err := os.OpenFile(binfileName, os.O_WRONLY, os.ModeAppend)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error: unable to open executable file: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create zip.Writer
|
|
||||||
zipWriter := zip.NewWriter(tmpZipfile)
|
|
||||||
|
|
||||||
for _, pkg := range pkgs {
|
|
||||||
// find boxes for this command
|
|
||||||
boxMap := findBoxes(pkg)
|
|
||||||
|
|
||||||
// notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
|
|
||||||
if len(boxMap) == 0 {
|
|
||||||
fmt.Printf("no calls to rice.FindBox() or rice.MustFindBox() found in import path `%s`\n", pkg.ImportPath)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
verbosef("\n")
|
|
||||||
|
|
||||||
for boxname := range boxMap {
|
|
||||||
appendedBoxName := strings.Replace(boxname, `/`, `-`, -1)
|
|
||||||
|
|
||||||
// walk box path's and insert files
|
|
||||||
boxPath := filepath.Clean(filepath.Join(pkg.Dir, boxname))
|
|
||||||
filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if info == nil {
|
|
||||||
fmt.Printf("Error: box \"%s\" not found on disk\n", path)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
// create zipFilename
|
|
||||||
zipFileName := filepath.Join(appendedBoxName, strings.TrimPrefix(path, boxPath))
|
|
||||||
// write directories as empty file with comment "dir"
|
|
||||||
if info.IsDir() {
|
|
||||||
_, err := zipWriter.CreateHeader(&zip.FileHeader{
|
|
||||||
Name: zipFileName,
|
|
||||||
Comment: "dir",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error creating dir in tmp zip: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// create zipFileWriter
|
|
||||||
zipFileHeader, err := zip.FileInfoHeader(info)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error creating zip FileHeader: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
zipFileHeader.Name = zipFileName
|
|
||||||
zipFileWriter, err := zipWriter.CreateHeader(zipFileHeader)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error creating file in tmp zip: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
srcFile, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error opening file to append: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
_, err = io.Copy(zipFileWriter, srcFile)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error copying file contents to zip: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
srcFile.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = zipWriter.Close()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error closing tmp zipfile: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tmpZipfile.Sync()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error syncing tmp zipfile: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
_, err = tmpZipfile.Seek(0, 0)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error seeking tmp zipfile: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
_, err = binfile.Seek(0, 2)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error seeking bin file: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.Copy(binfile, tmpZipfile)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error appending zipfile to executable: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
zipA := exec.Command("zip", "-A", binfileName)
|
|
||||||
err = zipA.Run()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error setting zip offset: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
33
vendor/github.com/GeertJohan/go.rice/rice/clean.go
generated
vendored
33
vendor/github.com/GeertJohan/go.rice/rice/clean.go
generated
vendored
@@ -1,33 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func operationClean(pkg *build.Package) {
|
|
||||||
filepath.Walk(pkg.Dir, func(filename string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error walking pkg dir to clean files: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
verbosef("checking file '%s'\n", filename)
|
|
||||||
if filepath.Base(filename) == "rice-box.go" ||
|
|
||||||
strings.HasSuffix(filename, ".rice-box.go") ||
|
|
||||||
strings.HasSuffix(filename, ".rice-box.syso") {
|
|
||||||
err := os.Remove(filename)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error removing file (%s): %s\n", filename, err)
|
|
||||||
os.Exit(-1)
|
|
||||||
}
|
|
||||||
verbosef("removed file '%s'\n", filename)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
158
vendor/github.com/GeertJohan/go.rice/rice/embed-go.go
generated
vendored
158
vendor/github.com/GeertJohan/go.rice/rice/embed-go.go
generated
vendored
@@ -1,158 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const boxFilename = "rice-box.go"
|
|
||||||
|
|
||||||
func operationEmbedGo(pkg *build.Package) {
|
|
||||||
|
|
||||||
boxMap := findBoxes(pkg)
|
|
||||||
|
|
||||||
// notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
|
|
||||||
if len(boxMap) == 0 {
|
|
||||||
fmt.Println("no calls to rice.FindBox() found")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
verbosef("\n")
|
|
||||||
var boxes []*boxDataType
|
|
||||||
|
|
||||||
for boxname := range boxMap {
|
|
||||||
// find path and filename for this box
|
|
||||||
boxPath := filepath.Join(pkg.Dir, boxname)
|
|
||||||
|
|
||||||
// Check to see if the path for the box is a symbolic link. If so, simply
|
|
||||||
// box what the symbolic link points to. Note: the filepath.Walk function
|
|
||||||
// will NOT follow any nested symbolic links. This only handles the case
|
|
||||||
// where the root of the box is a symbolic link.
|
|
||||||
symPath, serr := os.Readlink(boxPath)
|
|
||||||
if serr == nil {
|
|
||||||
boxPath = symPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// verbose info
|
|
||||||
verbosef("embedding box '%s' to '%s'\n", boxname, boxFilename)
|
|
||||||
|
|
||||||
// read box metadata
|
|
||||||
boxInfo, ierr := os.Stat(boxPath)
|
|
||||||
if ierr != nil {
|
|
||||||
fmt.Printf("Error: unable to access box at %s\n", boxPath)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create box datastructure (used by template)
|
|
||||||
box := &boxDataType{
|
|
||||||
BoxName: boxname,
|
|
||||||
UnixNow: boxInfo.ModTime().Unix(),
|
|
||||||
Files: make([]*fileDataType, 0),
|
|
||||||
Dirs: make(map[string]*dirDataType),
|
|
||||||
}
|
|
||||||
|
|
||||||
if !boxInfo.IsDir() {
|
|
||||||
fmt.Printf("Error: Box %s must point to a directory but points to %s instead\n",
|
|
||||||
boxname, boxPath)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill box datastructure with file data
|
|
||||||
filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error walking box: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
filename := strings.TrimPrefix(path, boxPath)
|
|
||||||
filename = strings.Replace(filename, "\\", "/", -1)
|
|
||||||
filename = strings.TrimPrefix(filename, "/")
|
|
||||||
if info.IsDir() {
|
|
||||||
dirData := &dirDataType{
|
|
||||||
Identifier: "dir" + nextIdentifier(),
|
|
||||||
FileName: filename,
|
|
||||||
ModTime: info.ModTime().Unix(),
|
|
||||||
ChildFiles: make([]*fileDataType, 0),
|
|
||||||
ChildDirs: make([]*dirDataType, 0),
|
|
||||||
}
|
|
||||||
verbosef("\tincludes dir: '%s'\n", dirData.FileName)
|
|
||||||
box.Dirs[dirData.FileName] = dirData
|
|
||||||
|
|
||||||
// add tree entry (skip for root, it'll create a recursion)
|
|
||||||
if dirData.FileName != "" {
|
|
||||||
pathParts := strings.Split(dirData.FileName, "/")
|
|
||||||
parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
|
|
||||||
parentDir.ChildDirs = append(parentDir.ChildDirs, dirData)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fileData := &fileDataType{
|
|
||||||
Identifier: "file" + nextIdentifier(),
|
|
||||||
FileName: filename,
|
|
||||||
ModTime: info.ModTime().Unix(),
|
|
||||||
}
|
|
||||||
verbosef("\tincludes file: '%s'\n", fileData.FileName)
|
|
||||||
fileData.Content, err = ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error reading file content while walking box: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
box.Files = append(box.Files, fileData)
|
|
||||||
|
|
||||||
// add tree entry
|
|
||||||
pathParts := strings.Split(fileData.FileName, "/")
|
|
||||||
parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
|
|
||||||
if parentDir == nil {
|
|
||||||
fmt.Printf("Error: parent of %s is not within the box\n", path)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
parentDir.ChildFiles = append(parentDir.ChildFiles, fileData)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
boxes = append(boxes, box)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
embedSourceUnformated := bytes.NewBuffer(make([]byte, 0))
|
|
||||||
|
|
||||||
// execute template to buffer
|
|
||||||
err := tmplEmbeddedBox.Execute(
|
|
||||||
embedSourceUnformated,
|
|
||||||
embedFileDataType{pkg.Name, boxes},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error writing embedded box to file (template execute): %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// format the source code
|
|
||||||
embedSource, err := format.Source(embedSourceUnformated.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error formatting embedSource: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create go file for box
|
|
||||||
boxFile, err := os.Create(filepath.Join(pkg.Dir, boxFilename))
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error creating embedded box file: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer boxFile.Close()
|
|
||||||
|
|
||||||
// write source to file
|
|
||||||
_, err = io.Copy(boxFile, bytes.NewBuffer(embedSource))
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error writing embedSource to file: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
204
vendor/github.com/GeertJohan/go.rice/rice/embed-syso.go
generated
vendored
204
vendor/github.com/GeertJohan/go.rice/rice/embed-syso.go
generated
vendored
@@ -1,204 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/gob"
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/GeertJohan/go.rice/embedded"
|
|
||||||
"github.com/akavel/rsrc/coff"
|
|
||||||
)
|
|
||||||
|
|
||||||
type sizedReader struct {
|
|
||||||
*bytes.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s sizedReader) Size() int64 {
|
|
||||||
return int64(s.Len())
|
|
||||||
}
|
|
||||||
|
|
||||||
var tmplEmbeddedSysoHelper *template.Template
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var err error
|
|
||||||
tmplEmbeddedSysoHelper, err = template.New("embeddedSysoHelper").Parse(`package {{.Package}}
|
|
||||||
// ############# GENERATED CODE #####################
|
|
||||||
// ## This file was generated by the rice tool.
|
|
||||||
// ## Do not edit unless you know what you're doing.
|
|
||||||
// ##################################################
|
|
||||||
|
|
||||||
// extern char _bricebox_{{.Symname}}[], _ericebox_{{.Symname}};
|
|
||||||
// int get_{{.Symname}}_length() {
|
|
||||||
// return &_ericebox_{{.Symname}} - _bricebox_{{.Symname}};
|
|
||||||
// }
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/gob"
|
|
||||||
"github.com/GeertJohan/go.rice/embedded"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ptr := unsafe.Pointer(&C._bricebox_{{.Symname}})
|
|
||||||
bts := C.GoBytes(ptr, C.get_{{.Symname}}_length())
|
|
||||||
embeddedBox := &embedded.EmbeddedBox{}
|
|
||||||
err := gob.NewDecoder(bytes.NewReader(bts)).Decode(embeddedBox)
|
|
||||||
if err != nil {
|
|
||||||
panic("error decoding embedded box: "+err.Error())
|
|
||||||
}
|
|
||||||
embeddedBox.Link()
|
|
||||||
embedded.RegisterEmbeddedBox(embeddedBox.Name, embeddedBox)
|
|
||||||
}`)
|
|
||||||
if err != nil {
|
|
||||||
panic("could not parse template embeddedSysoHelper: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type embeddedSysoHelperData struct {
|
|
||||||
Package string
|
|
||||||
Symname string
|
|
||||||
}
|
|
||||||
|
|
||||||
func operationEmbedSyso(pkg *build.Package) {
|
|
||||||
|
|
||||||
regexpSynameReplacer := regexp.MustCompile(`[^a-z0-9_]`)
|
|
||||||
|
|
||||||
boxMap := findBoxes(pkg)
|
|
||||||
|
|
||||||
// notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
|
|
||||||
if len(boxMap) == 0 {
|
|
||||||
fmt.Println("no calls to rice.FindBox() found")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
verbosef("\n")
|
|
||||||
|
|
||||||
for boxname := range boxMap {
|
|
||||||
// find path and filename for this box
|
|
||||||
boxPath := filepath.Join(pkg.Dir, boxname)
|
|
||||||
boxFilename := strings.Replace(boxname, "/", "-", -1)
|
|
||||||
boxFilename = strings.Replace(boxFilename, "..", "back", -1)
|
|
||||||
boxFilename = strings.Replace(boxFilename, ".", "-", -1)
|
|
||||||
|
|
||||||
// verbose info
|
|
||||||
verbosef("embedding box '%s'\n", boxname)
|
|
||||||
verbosef("\tto file %s\n", boxFilename)
|
|
||||||
|
|
||||||
// read box metadata
|
|
||||||
boxInfo, ierr := os.Stat(boxPath)
|
|
||||||
if ierr != nil {
|
|
||||||
fmt.Printf("Error: unable to access box at %s\n", boxPath)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create box datastructure (used by template)
|
|
||||||
box := &embedded.EmbeddedBox{
|
|
||||||
Name: boxname,
|
|
||||||
Time: boxInfo.ModTime(),
|
|
||||||
EmbedType: embedded.EmbedTypeSyso,
|
|
||||||
Files: make(map[string]*embedded.EmbeddedFile),
|
|
||||||
Dirs: make(map[string]*embedded.EmbeddedDir),
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill box datastructure with file data
|
|
||||||
filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error walking box: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
filename := strings.TrimPrefix(path, boxPath)
|
|
||||||
filename = strings.Replace(filename, "\\", "/", -1)
|
|
||||||
filename = strings.TrimPrefix(filename, "/")
|
|
||||||
if info.IsDir() {
|
|
||||||
embeddedDir := &embedded.EmbeddedDir{
|
|
||||||
Filename: filename,
|
|
||||||
DirModTime: info.ModTime(),
|
|
||||||
}
|
|
||||||
verbosef("\tincludes dir: '%s'\n", embeddedDir.Filename)
|
|
||||||
box.Dirs[embeddedDir.Filename] = embeddedDir
|
|
||||||
|
|
||||||
// add tree entry (skip for root, it'll create a recursion)
|
|
||||||
if embeddedDir.Filename != "" {
|
|
||||||
pathParts := strings.Split(embeddedDir.Filename, "/")
|
|
||||||
parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
|
|
||||||
parentDir.ChildDirs = append(parentDir.ChildDirs, embeddedDir)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
embeddedFile := &embedded.EmbeddedFile{
|
|
||||||
Filename: filename,
|
|
||||||
FileModTime: info.ModTime(),
|
|
||||||
Content: "",
|
|
||||||
}
|
|
||||||
verbosef("\tincludes file: '%s'\n", embeddedFile.Filename)
|
|
||||||
contentBytes, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error reading file content while walking box: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
embeddedFile.Content = string(contentBytes)
|
|
||||||
box.Files[embeddedFile.Filename] = embeddedFile
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
// encode embedded box to gob file
|
|
||||||
boxGobBuf := &bytes.Buffer{}
|
|
||||||
err := gob.NewEncoder(boxGobBuf).Encode(box)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error encoding box to gob: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
verbosef("gob-encoded embeddedBox is %d bytes large\n", boxGobBuf.Len())
|
|
||||||
|
|
||||||
// write coff
|
|
||||||
symname := regexpSynameReplacer.ReplaceAllString(boxname, "_")
|
|
||||||
createCoffSyso(boxname, symname, "386", boxGobBuf.Bytes())
|
|
||||||
createCoffSyso(boxname, symname, "amd64", boxGobBuf.Bytes())
|
|
||||||
|
|
||||||
// write go
|
|
||||||
sysoHelperData := embeddedSysoHelperData{
|
|
||||||
Package: pkg.Name,
|
|
||||||
Symname: symname,
|
|
||||||
}
|
|
||||||
fileSysoHelper, err := os.Create(boxFilename + ".rice-box.go")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error creating syso helper: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
err = tmplEmbeddedSysoHelper.Execute(fileSysoHelper, sysoHelperData)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error executing tmplEmbeddedSysoHelper: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createCoffSyso(boxFilename string, symname string, arch string, data []byte) {
|
|
||||||
boxCoff := coff.NewRDATA()
|
|
||||||
switch arch {
|
|
||||||
case "386":
|
|
||||||
case "amd64":
|
|
||||||
boxCoff.FileHeader.Machine = 0x8664
|
|
||||||
default:
|
|
||||||
panic("invalid arch")
|
|
||||||
}
|
|
||||||
boxCoff.AddData("_bricebox_"+symname, sizedReader{bytes.NewReader(data)})
|
|
||||||
boxCoff.AddData("_ericebox_"+symname, io.NewSectionReader(strings.NewReader("\000\000"), 0, 2)) // TODO: why? copied from rsrc, which copied it from as-generated
|
|
||||||
boxCoff.Freeze()
|
|
||||||
err := writeCoff(boxCoff, boxFilename+"_"+arch+".rice-box.syso")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error writing %s coff/.syso: %v\n", arch, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
150
vendor/github.com/GeertJohan/go.rice/rice/find.go
generated
vendored
150
vendor/github.com/GeertJohan/go.rice/rice/find.go
generated
vendored
@@ -1,150 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
|
||||||
"go/build"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func badArgument(fileset *token.FileSet, p token.Pos) {
|
|
||||||
pos := fileset.Position(p)
|
|
||||||
filename := pos.Filename
|
|
||||||
base, err := os.Getwd()
|
|
||||||
if err == nil {
|
|
||||||
rpath, perr := filepath.Rel(base, pos.Filename)
|
|
||||||
if perr == nil {
|
|
||||||
filename = rpath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf("%s:%d: Error: found call to rice.FindBox, "+
|
|
||||||
"but argument must be a string literal.\n", filename, pos.Line)
|
|
||||||
fmt.Println(msg)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func findBoxes(pkg *build.Package) map[string]bool {
|
|
||||||
// create map of boxes to embed
|
|
||||||
var boxMap = make(map[string]bool)
|
|
||||||
|
|
||||||
// create one list of files for this package
|
|
||||||
filenames := make([]string, 0, len(pkg.GoFiles)+len(pkg.CgoFiles))
|
|
||||||
filenames = append(filenames, pkg.GoFiles...)
|
|
||||||
filenames = append(filenames, pkg.CgoFiles...)
|
|
||||||
|
|
||||||
// loop over files, search for rice.FindBox(..) calls
|
|
||||||
for _, filename := range filenames {
|
|
||||||
// find full filepath
|
|
||||||
fullpath := filepath.Join(pkg.Dir, filename)
|
|
||||||
if strings.HasSuffix(filename, "rice-box.go") {
|
|
||||||
// Ignore *.rice-box.go files
|
|
||||||
verbosef("skipping file %q\n", fullpath)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
verbosef("scanning file %q\n", fullpath)
|
|
||||||
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
f, err := parser.ParseFile(fset, fullpath, nil, 0)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var riceIsImported bool
|
|
||||||
ricePkgName := "rice"
|
|
||||||
for _, imp := range f.Imports {
|
|
||||||
if strings.HasSuffix(imp.Path.Value, "go.rice\"") {
|
|
||||||
if imp.Name != nil {
|
|
||||||
ricePkgName = imp.Name.Name
|
|
||||||
}
|
|
||||||
riceIsImported = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !riceIsImported {
|
|
||||||
// Rice wasn't imported, so we won't find a box.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ricePkgName == "_" {
|
|
||||||
// Rice pkg is unnamed, so we won't find a box.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inspect AST, looking for calls to (Must)?FindBox.
|
|
||||||
// First parameter of the func must be a basic literal.
|
|
||||||
// Identifiers won't be resolved.
|
|
||||||
var nextIdentIsBoxFunc bool
|
|
||||||
var nextBasicLitParamIsBoxName bool
|
|
||||||
var boxCall token.Pos
|
|
||||||
var variableToRemember string
|
|
||||||
var validVariablesForBoxes map[string]bool = make(map[string]bool)
|
|
||||||
|
|
||||||
ast.Inspect(f, func(node ast.Node) bool {
|
|
||||||
if node == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch x := node.(type) {
|
|
||||||
// this case fixes the var := func() style assignments, not assignments to vars declared separately from the assignment.
|
|
||||||
case *ast.AssignStmt:
|
|
||||||
var assign = node.(*ast.AssignStmt)
|
|
||||||
name, found := assign.Lhs[0].(*ast.Ident)
|
|
||||||
if found {
|
|
||||||
variableToRemember = name.Name
|
|
||||||
composite, first := assign.Rhs[0].(*ast.CompositeLit)
|
|
||||||
if first {
|
|
||||||
riceSelector, second := composite.Type.(*ast.SelectorExpr)
|
|
||||||
|
|
||||||
if second {
|
|
||||||
callCorrect := riceSelector.Sel.Name == "Config"
|
|
||||||
packageName, third := riceSelector.X.(*ast.Ident)
|
|
||||||
|
|
||||||
if third && callCorrect && packageName.Name == ricePkgName {
|
|
||||||
validVariablesForBoxes[name.Name] = true
|
|
||||||
verbosef("\tfound variable, saving to scan for boxes: %q\n", name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *ast.Ident:
|
|
||||||
if nextIdentIsBoxFunc || ricePkgName == "." {
|
|
||||||
nextIdentIsBoxFunc = false
|
|
||||||
if x.Name == "FindBox" || x.Name == "MustFindBox" {
|
|
||||||
nextBasicLitParamIsBoxName = true
|
|
||||||
boxCall = x.Pos()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if x.Name == ricePkgName || validVariablesForBoxes[x.Name] {
|
|
||||||
nextIdentIsBoxFunc = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *ast.BasicLit:
|
|
||||||
if nextBasicLitParamIsBoxName {
|
|
||||||
if x.Kind == token.STRING {
|
|
||||||
nextBasicLitParamIsBoxName = false
|
|
||||||
// trim "" or ``
|
|
||||||
name := x.Value[1 : len(x.Value)-1]
|
|
||||||
boxMap[name] = true
|
|
||||||
verbosef("\tfound box %q\n", name)
|
|
||||||
} else {
|
|
||||||
badArgument(fset, boxCall)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
if nextIdentIsBoxFunc {
|
|
||||||
nextIdentIsBoxFunc = false
|
|
||||||
}
|
|
||||||
if nextBasicLitParamIsBoxName {
|
|
||||||
badArgument(fset, boxCall)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return boxMap
|
|
||||||
}
|
|
||||||
80
vendor/github.com/GeertJohan/go.rice/rice/flags.go
generated
vendored
80
vendor/github.com/GeertJohan/go.rice/rice/flags.go
generated
vendored
@@ -1,80 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
goflags "github.com/jessevdk/go-flags" // rename import to `goflags` (file scope) so we can use `var flags` (package scope)
|
|
||||||
)
|
|
||||||
|
|
||||||
// flags
|
|
||||||
var flags struct {
|
|
||||||
Verbose bool `long:"verbose" short:"v" description:"Show verbose debug information"`
|
|
||||||
ImportPaths []string `long:"import-path" short:"i" description:"Import path(s) to use. Using PWD when left empty. Specify multiple times for more import paths to append"`
|
|
||||||
|
|
||||||
Append struct {
|
|
||||||
Executable string `long:"exec" description:"Executable to append" required:"true"`
|
|
||||||
} `command:"append"`
|
|
||||||
|
|
||||||
EmbedGo struct{} `command:"embed-go" alias:"embed"`
|
|
||||||
EmbedSyso struct{} `command:"embed-syso"`
|
|
||||||
Clean struct{} `command:"clean"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// flags parser
|
|
||||||
var flagsParser *goflags.Parser
|
|
||||||
|
|
||||||
// initFlags parses the given flags.
|
|
||||||
// when the user asks for help (-h or --help): the application exists with status 0
|
|
||||||
// when unexpected flags is given: the application exits with status 1
|
|
||||||
func parseArguments() {
|
|
||||||
// create flags parser in global var, for flagsParser.Active.Name (operation)
|
|
||||||
flagsParser = goflags.NewParser(&flags, goflags.Default)
|
|
||||||
|
|
||||||
// parse flags
|
|
||||||
args, err := flagsParser.Parse()
|
|
||||||
if err != nil {
|
|
||||||
// assert the err to be a flags.Error
|
|
||||||
flagError := err.(*goflags.Error)
|
|
||||||
if flagError.Type == goflags.ErrHelp {
|
|
||||||
// user asked for help on flags.
|
|
||||||
// program can exit successfully
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
if flagError.Type == goflags.ErrUnknownFlag {
|
|
||||||
fmt.Println("Use --help to view available options.")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if flagError.Type == goflags.ErrRequired {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
fmt.Printf("Error parsing flags: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// error on left-over arguments
|
|
||||||
if len(args) > 0 {
|
|
||||||
fmt.Printf("Unexpected arguments: %s\nUse --help to view available options.", args)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// default ImportPath to pwd when not set
|
|
||||||
if len(flags.ImportPaths) == 0 {
|
|
||||||
pwd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error getting pwd: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
verbosef("using pwd as import path\n")
|
|
||||||
// find non-absolute path for this pwd
|
|
||||||
pkg, err := build.ImportDir(pwd, build.FindOnly)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error using current directory as import path: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
flags.ImportPaths = append(flags.ImportPaths, pkg.ImportPath)
|
|
||||||
verbosef("using import paths: %s\n", flags.ImportPaths)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
vendor/github.com/GeertJohan/go.rice/rice/identifier.go
generated
vendored
14
vendor/github.com/GeertJohan/go.rice/rice/identifier.go
generated
vendored
@@ -1,14 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/GeertJohan/go.incremental"
|
|
||||||
)
|
|
||||||
|
|
||||||
var identifierCount incremental.Uint64
|
|
||||||
|
|
||||||
func nextIdentifier() string {
|
|
||||||
num := identifierCount.Next()
|
|
||||||
return strconv.FormatUint(num, 36) // 0123456789abcdefghijklmnopqrstuvwxyz
|
|
||||||
}
|
|
||||||
68
vendor/github.com/GeertJohan/go.rice/rice/main.go
generated
vendored
68
vendor/github.com/GeertJohan/go.rice/rice/main.go
generated
vendored
@@ -1,68 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// parser arguments
|
|
||||||
parseArguments()
|
|
||||||
|
|
||||||
// find package for path
|
|
||||||
var pkgs []*build.Package
|
|
||||||
for _, importPath := range flags.ImportPaths {
|
|
||||||
pkg := pkgForPath(importPath)
|
|
||||||
pkgs = append(pkgs, pkg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch on the operation to perform
|
|
||||||
switch flagsParser.Active.Name {
|
|
||||||
case "embed", "embed-go":
|
|
||||||
for _, pkg := range pkgs {
|
|
||||||
operationEmbedGo(pkg)
|
|
||||||
}
|
|
||||||
case "embed-syso":
|
|
||||||
log.Println("WARNING: embedding .syso is experimental..")
|
|
||||||
for _, pkg := range pkgs {
|
|
||||||
operationEmbedSyso(pkg)
|
|
||||||
}
|
|
||||||
case "append":
|
|
||||||
operationAppend(pkgs)
|
|
||||||
case "clean":
|
|
||||||
for _, pkg := range pkgs {
|
|
||||||
operationClean(pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// all done
|
|
||||||
verbosef("\n")
|
|
||||||
verbosef("rice finished successfully\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function to get *build.Package for given path
|
|
||||||
func pkgForPath(path string) *build.Package {
|
|
||||||
// get pwd for relative imports
|
|
||||||
pwd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error getting pwd (required for relative imports): %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// read full package information
|
|
||||||
pkg, err := build.Import(path, pwd, 0)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error reading package: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkg
|
|
||||||
}
|
|
||||||
|
|
||||||
func verbosef(format string, stuff ...interface{}) {
|
|
||||||
if flags.Verbose {
|
|
||||||
log.Printf(format, stuff...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
98
vendor/github.com/GeertJohan/go.rice/rice/templates.go
generated
vendored
98
vendor/github.com/GeertJohan/go.rice/rice/templates.go
generated
vendored
@@ -1,98 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
var tmplEmbeddedBox *template.Template
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// parse embedded box template
|
|
||||||
tmplEmbeddedBox, err = template.New("embeddedBox").Parse(`package {{.Package}}
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/GeertJohan/go.rice/embedded"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
{{range .Boxes}}
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
// define files
|
|
||||||
{{range .Files}}{{.Identifier}} := &embedded.EmbeddedFile{
|
|
||||||
Filename: ` + "`" + `{{.FileName}}` + "`" + `,
|
|
||||||
FileModTime: time.Unix({{.ModTime}}, 0),
|
|
||||||
Content: string({{.Content | printf "%q"}}),
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
// define dirs
|
|
||||||
{{range .Dirs}}{{.Identifier}} := &embedded.EmbeddedDir{
|
|
||||||
Filename: ` + "`" + `{{.FileName}}` + "`" + `,
|
|
||||||
DirModTime: time.Unix({{.ModTime}}, 0),
|
|
||||||
ChildFiles: []*embedded.EmbeddedFile{
|
|
||||||
{{range .ChildFiles}}{{.Identifier}}, // {{.FileName}}
|
|
||||||
{{end}}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
// link ChildDirs
|
|
||||||
{{range .Dirs}}{{.Identifier}}.ChildDirs = []*embedded.EmbeddedDir{
|
|
||||||
{{range .ChildDirs}}{{.Identifier}}, // {{.FileName}}
|
|
||||||
{{end}}
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
// register embeddedBox
|
|
||||||
embedded.RegisterEmbeddedBox(` + "`" + `{{.BoxName}}` + "`" + `, &embedded.EmbeddedBox{
|
|
||||||
Name: ` + "`" + `{{.BoxName}}` + "`" + `,
|
|
||||||
Time: time.Unix({{.UnixNow}}, 0),
|
|
||||||
Dirs: map[string]*embedded.EmbeddedDir{
|
|
||||||
{{range .Dirs}}"{{.FileName}}": {{.Identifier}},
|
|
||||||
{{end}}
|
|
||||||
},
|
|
||||||
Files: map[string]*embedded.EmbeddedFile{
|
|
||||||
{{range .Files}}"{{.FileName}}": {{.Identifier}},
|
|
||||||
{{end}}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
{{end}}`)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("error parsing embedded box template: %s\n", err)
|
|
||||||
os.Exit(-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type embedFileDataType struct {
|
|
||||||
Package string
|
|
||||||
Boxes []*boxDataType
|
|
||||||
}
|
|
||||||
|
|
||||||
type boxDataType struct {
|
|
||||||
BoxName string
|
|
||||||
UnixNow int64
|
|
||||||
Files []*fileDataType
|
|
||||||
Dirs map[string]*dirDataType
|
|
||||||
}
|
|
||||||
|
|
||||||
type fileDataType struct {
|
|
||||||
Identifier string
|
|
||||||
FileName string
|
|
||||||
Content []byte
|
|
||||||
ModTime int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type dirDataType struct {
|
|
||||||
Identifier string
|
|
||||||
FileName string
|
|
||||||
Content []byte
|
|
||||||
ModTime int64
|
|
||||||
ChildDirs []*dirDataType
|
|
||||||
ChildFiles []*fileDataType
|
|
||||||
}
|
|
||||||
22
vendor/github.com/GeertJohan/go.rice/rice/util.go
generated
vendored
22
vendor/github.com/GeertJohan/go.rice/rice/util.go
generated
vendored
@@ -1,22 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// randomString generates a pseudo-random alpha-numeric string with given length.
|
|
||||||
func randomString(length int) string {
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
k := make([]rune, length)
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
c := rand.Intn(35)
|
|
||||||
if c < 10 {
|
|
||||||
c += 48 // numbers (0-9) (0+48 == 48 == '0', 9+48 == 57 == '9')
|
|
||||||
} else {
|
|
||||||
c += 87 // lower case alphabets (a-z) (10+87 == 97 == 'a', 35+87 == 122 = 'z')
|
|
||||||
}
|
|
||||||
k[i] = rune(c)
|
|
||||||
}
|
|
||||||
return string(k)
|
|
||||||
}
|
|
||||||
42
vendor/github.com/GeertJohan/go.rice/rice/writecoff.go
generated
vendored
42
vendor/github.com/GeertJohan/go.rice/rice/writecoff.go
generated
vendored
@@ -1,42 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/akavel/rsrc/binutil"
|
|
||||||
"github.com/akavel/rsrc/coff"
|
|
||||||
)
|
|
||||||
|
|
||||||
// copied from github.com/akavel/rsrc
|
|
||||||
// LICENSE: MIT
|
|
||||||
// Copyright 2013-2014 The rsrc Authors. (https://github.com/akavel/rsrc/blob/master/AUTHORS)
|
|
||||||
func writeCoff(coff *coff.Coff, fnameout string) error {
|
|
||||||
out, err := os.Create(fnameout)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
w := binutil.Writer{W: out}
|
|
||||||
|
|
||||||
// write the resulting file to disk
|
|
||||||
binutil.Walk(coff, func(v reflect.Value, path string) error {
|
|
||||||
if binutil.Plain(v.Kind()) {
|
|
||||||
w.WriteLE(v.Interface())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
vv, ok := v.Interface().(binutil.SizedReader)
|
|
||||||
if ok {
|
|
||||||
w.WriteFromSized(vv)
|
|
||||||
return binutil.WALK_SKIP
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if w.Err != nil {
|
|
||||||
return fmt.Errorf("Error writing output file: %s", w.Err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
19
vendor/github.com/GeertJohan/go.rice/sort.go
generated
vendored
19
vendor/github.com/GeertJohan/go.rice/sort.go
generated
vendored
@@ -1,19 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
// SortByName allows an array of os.FileInfo objects
|
|
||||||
// to be easily sorted by filename using sort.Sort(SortByName(array))
|
|
||||||
type SortByName []os.FileInfo
|
|
||||||
|
|
||||||
func (f SortByName) Len() int { return len(f) }
|
|
||||||
func (f SortByName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
|
|
||||||
func (f SortByName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
|
|
||||||
|
|
||||||
// SortByModified allows an array of os.FileInfo objects
|
|
||||||
// to be easily sorted by modified date using sort.Sort(SortByModified(array))
|
|
||||||
type SortByModified []os.FileInfo
|
|
||||||
|
|
||||||
func (f SortByModified) Len() int { return len(f) }
|
|
||||||
func (f SortByModified) Less(i, j int) bool { return f[i].ModTime().Unix() > f[j].ModTime().Unix() }
|
|
||||||
func (f SortByModified) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
|
|
||||||
252
vendor/github.com/GeertJohan/go.rice/virtual.go
generated
vendored
252
vendor/github.com/GeertJohan/go.rice/virtual.go
generated
vendored
@@ -1,252 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/GeertJohan/go.rice/embedded"
|
|
||||||
)
|
|
||||||
|
|
||||||
//++ TODO: IDEA: merge virtualFile and virtualDir, this decreases work done by rice.File
|
|
||||||
|
|
||||||
// Error indicating some function is not implemented yet (but available to satisfy an interface)
|
|
||||||
var ErrNotImplemented = errors.New("not implemented yet")
|
|
||||||
|
|
||||||
// virtualFile is a 'stateful' virtual file.
|
|
||||||
// virtualFile wraps an *EmbeddedFile for a call to Box.Open() and virtualizes 'read cursor' (offset) and 'closing'.
|
|
||||||
// virtualFile is only internally visible and should be exposed through rice.File
|
|
||||||
type virtualFile struct {
|
|
||||||
*embedded.EmbeddedFile // the actual embedded file, embedded to obtain methods
|
|
||||||
offset int64 // read position on the virtual file
|
|
||||||
closed bool // closed when true
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new virtualFile for given EmbeddedFile
|
|
||||||
func newVirtualFile(ef *embedded.EmbeddedFile) *virtualFile {
|
|
||||||
vf := &virtualFile{
|
|
||||||
EmbeddedFile: ef,
|
|
||||||
offset: 0,
|
|
||||||
closed: false,
|
|
||||||
}
|
|
||||||
return vf
|
|
||||||
}
|
|
||||||
|
|
||||||
//++ TODO check for nil pointers in all these methods. When so: return os.PathError with Err: os.ErrInvalid
|
|
||||||
|
|
||||||
func (vf *virtualFile) close() error {
|
|
||||||
if vf.closed {
|
|
||||||
return &os.PathError{
|
|
||||||
Op: "close",
|
|
||||||
Path: vf.EmbeddedFile.Filename,
|
|
||||||
Err: errors.New("already closed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vf.EmbeddedFile = nil
|
|
||||||
vf.closed = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vf *virtualFile) stat() (os.FileInfo, error) {
|
|
||||||
if vf.closed {
|
|
||||||
return nil, &os.PathError{
|
|
||||||
Op: "stat",
|
|
||||||
Path: vf.EmbeddedFile.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (*embeddedFileInfo)(vf.EmbeddedFile), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vf *virtualFile) readdir(count int) ([]os.FileInfo, error) {
|
|
||||||
if vf.closed {
|
|
||||||
return nil, &os.PathError{
|
|
||||||
Op: "readdir",
|
|
||||||
Path: vf.EmbeddedFile.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//TODO: return proper error for a readdir() call on a file
|
|
||||||
return nil, ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vf *virtualFile) read(bts []byte) (int, error) {
|
|
||||||
if vf.closed {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "read",
|
|
||||||
Path: vf.EmbeddedFile.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end := vf.offset + int64(len(bts))
|
|
||||||
|
|
||||||
if end >= int64(len(vf.Content)) {
|
|
||||||
// end of file, so return what we have + EOF
|
|
||||||
n := copy(bts, vf.Content[vf.offset:])
|
|
||||||
vf.offset = 0
|
|
||||||
return n, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
n := copy(bts, vf.Content[vf.offset:end])
|
|
||||||
vf.offset += int64(n)
|
|
||||||
return n, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vf *virtualFile) seek(offset int64, whence int) (int64, error) {
|
|
||||||
if vf.closed {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "seek",
|
|
||||||
Path: vf.EmbeddedFile.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var e error
|
|
||||||
|
|
||||||
//++ TODO: check if this is correct implementation for seek
|
|
||||||
switch whence {
|
|
||||||
case os.SEEK_SET:
|
|
||||||
//++ check if new offset isn't out of bounds, set e when it is, then break out of switch
|
|
||||||
vf.offset = offset
|
|
||||||
case os.SEEK_CUR:
|
|
||||||
//++ check if new offset isn't out of bounds, set e when it is, then break out of switch
|
|
||||||
vf.offset += offset
|
|
||||||
case os.SEEK_END:
|
|
||||||
//++ check if new offset isn't out of bounds, set e when it is, then break out of switch
|
|
||||||
vf.offset = int64(len(vf.EmbeddedFile.Content)) - offset
|
|
||||||
}
|
|
||||||
|
|
||||||
if e != nil {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "seek",
|
|
||||||
Path: vf.Filename,
|
|
||||||
Err: e,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return vf.offset, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtualDir is a 'stateful' virtual directory.
|
|
||||||
// virtualDir wraps an *EmbeddedDir for a call to Box.Open() and virtualizes 'closing'.
|
|
||||||
// virtualDir is only internally visible and should be exposed through rice.File
|
|
||||||
type virtualDir struct {
|
|
||||||
*embedded.EmbeddedDir
|
|
||||||
offset int // readdir position on the directory
|
|
||||||
closed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new virtualDir for given EmbeddedDir
|
|
||||||
func newVirtualDir(ed *embedded.EmbeddedDir) *virtualDir {
|
|
||||||
vd := &virtualDir{
|
|
||||||
EmbeddedDir: ed,
|
|
||||||
offset: 0,
|
|
||||||
closed: false,
|
|
||||||
}
|
|
||||||
return vd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vd *virtualDir) close() error {
|
|
||||||
//++ TODO: needs sync mutex?
|
|
||||||
if vd.closed {
|
|
||||||
return &os.PathError{
|
|
||||||
Op: "close",
|
|
||||||
Path: vd.EmbeddedDir.Filename,
|
|
||||||
Err: errors.New("already closed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vd.closed = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vd *virtualDir) stat() (os.FileInfo, error) {
|
|
||||||
if vd.closed {
|
|
||||||
return nil, &os.PathError{
|
|
||||||
Op: "stat",
|
|
||||||
Path: vd.EmbeddedDir.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (*embeddedDirInfo)(vd.EmbeddedDir), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vd *virtualDir) readdir(n int) (fi []os.FileInfo, err error) {
|
|
||||||
|
|
||||||
if vd.closed {
|
|
||||||
return nil, &os.PathError{
|
|
||||||
Op: "readdir",
|
|
||||||
Path: vd.EmbeddedDir.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build up the array of our contents
|
|
||||||
var files []os.FileInfo
|
|
||||||
|
|
||||||
// Add the child directories
|
|
||||||
for _, child := range vd.ChildDirs {
|
|
||||||
child.Filename = filepath.Base(child.Filename)
|
|
||||||
files = append(files, (*embeddedDirInfo)(child))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the child files
|
|
||||||
for _, child := range vd.ChildFiles {
|
|
||||||
child.Filename = filepath.Base(child.Filename)
|
|
||||||
files = append(files, (*embeddedFileInfo)(child))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort it by filename (lexical order)
|
|
||||||
sort.Sort(SortByName(files))
|
|
||||||
|
|
||||||
// Return all contents if that's what is requested
|
|
||||||
if n <= 0 {
|
|
||||||
vd.offset = 0
|
|
||||||
return files, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If user has requested past the end of our list
|
|
||||||
// return what we can and send an EOF
|
|
||||||
if vd.offset+n >= len(files) {
|
|
||||||
offset := vd.offset
|
|
||||||
vd.offset = 0
|
|
||||||
return files[offset:], io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
offset := vd.offset
|
|
||||||
vd.offset += n
|
|
||||||
return files[offset : offset+n], nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vd *virtualDir) read(bts []byte) (int, error) {
|
|
||||||
if vd.closed {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "read",
|
|
||||||
Path: vd.EmbeddedDir.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "read",
|
|
||||||
Path: vd.EmbeddedDir.Filename,
|
|
||||||
Err: errors.New("is a directory"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vd *virtualDir) seek(offset int64, whence int) (int64, error) {
|
|
||||||
if vd.closed {
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "seek",
|
|
||||||
Path: vd.EmbeddedDir.Filename,
|
|
||||||
Err: errors.New("bad file descriptor"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, &os.PathError{
|
|
||||||
Op: "seek",
|
|
||||||
Path: vd.Filename,
|
|
||||||
Err: errors.New("is a directory"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
122
vendor/github.com/GeertJohan/go.rice/walk.go
generated
vendored
122
vendor/github.com/GeertJohan/go.rice/walk.go
generated
vendored
@@ -1,122 +0,0 @@
|
|||||||
package rice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Walk is like filepath.Walk()
|
|
||||||
// Visit http://golang.org/pkg/path/filepath/#Walk for more information
|
|
||||||
func (b *Box) Walk(path string, walkFn filepath.WalkFunc) error {
|
|
||||||
|
|
||||||
pathFile, err := b.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer pathFile.Close()
|
|
||||||
|
|
||||||
pathInfo, err := pathFile.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.IsAppended() || b.IsEmbedded() {
|
|
||||||
return b.walk(path, pathInfo, walkFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't have any embedded or appended box so use live filesystem mode
|
|
||||||
return filepath.Walk(b.absolutePath+string(os.PathSeparator)+path, func(path string, info os.FileInfo, err error) error {
|
|
||||||
|
|
||||||
// Strip out the box name from the returned paths
|
|
||||||
path = strings.TrimPrefix(path, b.absolutePath+string(os.PathSeparator))
|
|
||||||
return walkFn(path, info, err)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// walk recursively descends path.
|
|
||||||
// See walk() in $GOROOT/src/pkg/path/filepath/path.go
|
|
||||||
func (b *Box) walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
|
|
||||||
|
|
||||||
err := walkFn(path, info, nil)
|
|
||||||
if err != nil {
|
|
||||||
if info.IsDir() && err == filepath.SkipDir {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
names, err := b.readDirNames(path)
|
|
||||||
if err != nil {
|
|
||||||
return walkFn(path, info, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range names {
|
|
||||||
|
|
||||||
filename := filepath.Join(path, name)
|
|
||||||
fileObject, err := b.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer fileObject.Close()
|
|
||||||
|
|
||||||
fileInfo, err := fileObject.Stat()
|
|
||||||
if err != nil {
|
|
||||||
if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = b.walk(filename, fileInfo, walkFn)
|
|
||||||
if err != nil {
|
|
||||||
if !fileInfo.IsDir() || err != filepath.SkipDir {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// readDirNames reads the directory named by path and returns a sorted list of directory entries.
|
|
||||||
// See readDirNames() in $GOROOT/pkg/path/filepath/path.go
|
|
||||||
func (b *Box) readDirNames(path string) ([]string, error) {
|
|
||||||
|
|
||||||
f, err := b.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
stat, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !stat.IsDir() {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
infos, err := f.Readdir(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var names []string
|
|
||||||
|
|
||||||
for _, info := range infos {
|
|
||||||
names = append(names, info.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(names)
|
|
||||||
return names, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
22
vendor/github.com/Philipp15b/go-steam/.gitignore
generated
vendored
Normal file
22
vendor/github.com/Philipp15b/go-steam/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
3
vendor/github.com/Philipp15b/go-steam/.gitmodules
generated
vendored
Normal file
3
vendor/github.com/Philipp15b/go-steam/.gitmodules
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "generator/SteamKit"]
|
||||||
|
path = generator/SteamKit
|
||||||
|
url = https://github.com/Philipp15b/SteamKit.git
|
||||||
64
vendor/github.com/Philipp15b/go-steam/README.md
generated
vendored
Normal file
64
vendor/github.com/Philipp15b/go-steam/README.md
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# Steam for Go
|
||||||
|
|
||||||
|
This library implements Steam's protocol to allow automation of different actions on Steam without running an actual Steam client. It is based on [SteamKit2](https://github.com/SteamRE/SteamKit), a .NET library.
|
||||||
|
|
||||||
|
In addition, it contains APIs to Steam Community features, like trade offers and inventories.
|
||||||
|
|
||||||
|
Some of the currently implemented features:
|
||||||
|
|
||||||
|
* Trading and trade offers, including inventories and notifications
|
||||||
|
* Friend and group management
|
||||||
|
* Chatting with friends
|
||||||
|
* Persona states (online, offline, looking to trade, etc.)
|
||||||
|
* SteamGuard with two-factor authentication
|
||||||
|
* Team Fortress 2: Crafting, moving, naming and deleting items
|
||||||
|
|
||||||
|
If this is useful to you, there's also the [go-steamapi](https://github.com/Philipp15b/go-steamapi) package that wraps some of the official Steam Web API's types.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
go get github.com/Philipp15b/go-steam
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can view the documentation with the [`godoc`](http://golang.org/cmd/godoc) tool or
|
||||||
|
[online on godoc.org](http://godoc.org/github.com/Philipp15b/go-steam).
|
||||||
|
|
||||||
|
You should also take a look at the following sub-packages:
|
||||||
|
|
||||||
|
* [`gsbot`](http://godoc.org/github.com/Philipp15b/go-steam/gsbot) utilites that make writing bots easier
|
||||||
|
* [example bot](http://godoc.org/github.com/Philipp15b/go-steam/gsbot/gsbot) and [its source code](https://github.com/Philipp15b/go-steam/blob/master/gsbot/gsbot/gsbot.go)
|
||||||
|
* [`trade`](http://godoc.org/github.com/Philipp15b/go-steam/trade) for trading
|
||||||
|
* [`tradeoffer`](http://godoc.org/github.com/Philipp15b/go-steam/tradeoffer) for trade offers
|
||||||
|
* [`economy/inventory`](http://godoc.org/github.com/Philipp15b/go-steam/economy/inventory) for inventories
|
||||||
|
* [`tf2`](http://godoc.org/github.com/Philipp15b/go-steam/tf2) for Team Fortress 2 related things
|
||||||
|
|
||||||
|
## Working with go-steam
|
||||||
|
|
||||||
|
Whether you want to develop your own Steam bot or directly work on go-steam itself, there are are few things to know.
|
||||||
|
|
||||||
|
* If something is not working, check first if the same operation works (under the same conditions!) in the Steam client on that account. Maybe there's something go-steam doesn't handle correctly or you're missing a warning that's not obviously shown in go-steam. This is particularly important when working with trading since there are [restrictions](https://support.steampowered.com/kb_article.php?ref=1047-edfm-2932), for example newly authorized devices will not be able to trade for seven days.
|
||||||
|
* Since Steam does not maintain a public API for most of the things go-steam implements, you can expect that sometimes things break randomly. Especially the `trade` and `tradeoffer` packages have been affected in the past.
|
||||||
|
* Always gather as much information as possible. When you file an issue, be as precise and complete as you can. This makes debugging way easier.
|
||||||
|
* If you haven't noticed yet, expect to find lots of things out yourself. Debugging can be complicated and Steam's internals are too.
|
||||||
|
* Sometimes things break and other [SteamKit ports](https://github.com/SteamRE/SteamKit/wiki/Ports) are fixed already. Maybe take a look what people are saying over there? There's also the [SteamKit IRC channel](https://github.com/SteamRE/SteamKit/wiki#contact).
|
||||||
|
|
||||||
|
## Updating go-steam to a new SteamKit version
|
||||||
|
|
||||||
|
To update go-steam to a new version of SteamKit, do the following:
|
||||||
|
|
||||||
|
go get github.com/golang/protobuf/protoc-gen-go/
|
||||||
|
git submodule init && git submodule update
|
||||||
|
cd generator
|
||||||
|
go run generator.go clean proto steamlang
|
||||||
|
|
||||||
|
Make sure that `$GOPATH/bin` / `protoc-gen-go` is in your `$PATH`. You'll also need [`protoc`](https://developers.google.com/protocol-buffers/docs/downloads), the protocol buffer compiler. At the moment, we use Protocol Buffers 2.6.1 with `proco-gen-go`-[2402d76](https://github.com/golang/protobuf/tree/2402d76f3d41f928c7902a765dfc872356dd3aad).
|
||||||
|
|
||||||
|
To compile the Steam Language files, you also need the [.NET Framework](https://www.microsoft.com/net/downloads)
|
||||||
|
on Windows or [mono](http://www.go-mono.com/mono-downloads/download.html) on other operating systems.
|
||||||
|
|
||||||
|
Apply the protocol changes where necessary.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Steam for Go is licensed under the New BSD License. More information can be found in LICENSE.txt.
|
||||||
35
vendor/github.com/Philipp15b/go-steam/community/community.go
generated
vendored
35
vendor/github.com/Philipp15b/go-steam/community/community.go
generated
vendored
@@ -1,35 +0,0 @@
|
|||||||
package community
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/cookiejar"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
const cookiePath = "https://steamcommunity.com/"
|
|
||||||
|
|
||||||
func SetCookies(client *http.Client, sessionId, steamLogin, steamLoginSecure string) {
|
|
||||||
if client.Jar == nil {
|
|
||||||
client.Jar, _ = cookiejar.New(new(cookiejar.Options))
|
|
||||||
}
|
|
||||||
base, err := url.Parse(cookiePath)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
client.Jar.SetCookies(base, []*http.Cookie{
|
|
||||||
// It seems that, for some reason, Steam tries to URL-decode the cookie.
|
|
||||||
&http.Cookie{
|
|
||||||
Name: "sessionid",
|
|
||||||
Value: url.QueryEscape(sessionId),
|
|
||||||
},
|
|
||||||
// steamLogin is already URL-encoded.
|
|
||||||
&http.Cookie{
|
|
||||||
Name: "steamLogin",
|
|
||||||
Value: steamLogin,
|
|
||||||
},
|
|
||||||
&http.Cookie{
|
|
||||||
Name: "steamLoginSecure",
|
|
||||||
Value: steamLoginSecure,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
3651
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/base.pb.go
generated
vendored
3651
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/base.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
18413
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/dota_client.pb.go
generated
vendored
18413
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/dota_client.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
6123
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/dota_client_fantasy.pb.go
generated
vendored
6123
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/dota_client_fantasy.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
10997
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/dota_common.pb.go
generated
vendored
10997
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/dota_common.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
4441
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/econ.pb.go
generated
vendored
4441
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/econ.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1825
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/gcsdk.pb.go
generated
vendored
1825
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/gcsdk.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
579
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/system.pb.go
generated
vendored
579
vendor/github.com/Philipp15b/go-steam/dota/protocol/protobuf/system.pb.go
generated
vendored
@@ -1,579 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go.
|
|
||||||
// source: gcsystemmsgs.proto
|
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
package protobuf
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import fmt "fmt"
|
|
||||||
import math "math"
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the proto package protobuf is being compiled against.
|
|
||||||
const _ = proto.ProtoPackageIsVersion1
|
|
||||||
|
|
||||||
type EGCSystemMsg int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
EGCSystemMsg_k_EGCMsgInvalid EGCSystemMsg = 0
|
|
||||||
EGCSystemMsg_k_EGCMsgMulti EGCSystemMsg = 1
|
|
||||||
EGCSystemMsg_k_EGCMsgGenericReply EGCSystemMsg = 10
|
|
||||||
EGCSystemMsg_k_EGCMsgSystemBase EGCSystemMsg = 50
|
|
||||||
EGCSystemMsg_k_EGCMsgAchievementAwarded EGCSystemMsg = 51
|
|
||||||
EGCSystemMsg_k_EGCMsgConCommand EGCSystemMsg = 52
|
|
||||||
EGCSystemMsg_k_EGCMsgStartPlaying EGCSystemMsg = 53
|
|
||||||
EGCSystemMsg_k_EGCMsgStopPlaying EGCSystemMsg = 54
|
|
||||||
EGCSystemMsg_k_EGCMsgStartGameserver EGCSystemMsg = 55
|
|
||||||
EGCSystemMsg_k_EGCMsgStopGameserver EGCSystemMsg = 56
|
|
||||||
EGCSystemMsg_k_EGCMsgWGRequest EGCSystemMsg = 57
|
|
||||||
EGCSystemMsg_k_EGCMsgWGResponse EGCSystemMsg = 58
|
|
||||||
EGCSystemMsg_k_EGCMsgGetUserGameStatsSchema EGCSystemMsg = 59
|
|
||||||
EGCSystemMsg_k_EGCMsgGetUserGameStatsSchemaResponse EGCSystemMsg = 60
|
|
||||||
EGCSystemMsg_k_EGCMsgGetUserStatsDEPRECATED EGCSystemMsg = 61
|
|
||||||
EGCSystemMsg_k_EGCMsgGetUserStatsResponse EGCSystemMsg = 62
|
|
||||||
EGCSystemMsg_k_EGCMsgAppInfoUpdated EGCSystemMsg = 63
|
|
||||||
EGCSystemMsg_k_EGCMsgValidateSession EGCSystemMsg = 64
|
|
||||||
EGCSystemMsg_k_EGCMsgValidateSessionResponse EGCSystemMsg = 65
|
|
||||||
EGCSystemMsg_k_EGCMsgLookupAccountFromInput EGCSystemMsg = 66
|
|
||||||
EGCSystemMsg_k_EGCMsgSendHTTPRequest EGCSystemMsg = 67
|
|
||||||
EGCSystemMsg_k_EGCMsgSendHTTPRequestResponse EGCSystemMsg = 68
|
|
||||||
EGCSystemMsg_k_EGCMsgPreTestSetup EGCSystemMsg = 69
|
|
||||||
EGCSystemMsg_k_EGCMsgRecordSupportAction EGCSystemMsg = 70
|
|
||||||
EGCSystemMsg_k_EGCMsgGetAccountDetails_DEPRECATED EGCSystemMsg = 71
|
|
||||||
EGCSystemMsg_k_EGCMsgReceiveInterAppMessage EGCSystemMsg = 73
|
|
||||||
EGCSystemMsg_k_EGCMsgFindAccounts EGCSystemMsg = 74
|
|
||||||
EGCSystemMsg_k_EGCMsgPostAlert EGCSystemMsg = 75
|
|
||||||
EGCSystemMsg_k_EGCMsgGetLicenses EGCSystemMsg = 76
|
|
||||||
EGCSystemMsg_k_EGCMsgGetUserStats EGCSystemMsg = 77
|
|
||||||
EGCSystemMsg_k_EGCMsgGetCommands EGCSystemMsg = 78
|
|
||||||
EGCSystemMsg_k_EGCMsgGetCommandsResponse EGCSystemMsg = 79
|
|
||||||
EGCSystemMsg_k_EGCMsgAddFreeLicense EGCSystemMsg = 80
|
|
||||||
EGCSystemMsg_k_EGCMsgAddFreeLicenseResponse EGCSystemMsg = 81
|
|
||||||
EGCSystemMsg_k_EGCMsgGetIPLocation EGCSystemMsg = 82
|
|
||||||
EGCSystemMsg_k_EGCMsgGetIPLocationResponse EGCSystemMsg = 83
|
|
||||||
EGCSystemMsg_k_EGCMsgSystemStatsSchema EGCSystemMsg = 84
|
|
||||||
EGCSystemMsg_k_EGCMsgGetSystemStats EGCSystemMsg = 85
|
|
||||||
EGCSystemMsg_k_EGCMsgGetSystemStatsResponse EGCSystemMsg = 86
|
|
||||||
EGCSystemMsg_k_EGCMsgSendEmail EGCSystemMsg = 87
|
|
||||||
EGCSystemMsg_k_EGCMsgSendEmailResponse EGCSystemMsg = 88
|
|
||||||
EGCSystemMsg_k_EGCMsgGetEmailTemplate EGCSystemMsg = 89
|
|
||||||
EGCSystemMsg_k_EGCMsgGetEmailTemplateResponse EGCSystemMsg = 90
|
|
||||||
EGCSystemMsg_k_EGCMsgGrantGuestPass EGCSystemMsg = 91
|
|
||||||
EGCSystemMsg_k_EGCMsgGrantGuestPassResponse EGCSystemMsg = 92
|
|
||||||
EGCSystemMsg_k_EGCMsgGetAccountDetails EGCSystemMsg = 93
|
|
||||||
EGCSystemMsg_k_EGCMsgGetAccountDetailsResponse EGCSystemMsg = 94
|
|
||||||
EGCSystemMsg_k_EGCMsgGetPersonaNames EGCSystemMsg = 95
|
|
||||||
EGCSystemMsg_k_EGCMsgGetPersonaNamesResponse EGCSystemMsg = 96
|
|
||||||
EGCSystemMsg_k_EGCMsgMultiplexMsg EGCSystemMsg = 97
|
|
||||||
EGCSystemMsg_k_EGCMsgWebAPIRegisterInterfaces EGCSystemMsg = 101
|
|
||||||
EGCSystemMsg_k_EGCMsgWebAPIJobRequest EGCSystemMsg = 102
|
|
||||||
EGCSystemMsg_k_EGCMsgWebAPIJobRequestHttpResponse EGCSystemMsg = 104
|
|
||||||
EGCSystemMsg_k_EGCMsgWebAPIJobRequestForwardResponse EGCSystemMsg = 105
|
|
||||||
EGCSystemMsg_k_EGCMsgMemCachedGet EGCSystemMsg = 200
|
|
||||||
EGCSystemMsg_k_EGCMsgMemCachedGetResponse EGCSystemMsg = 201
|
|
||||||
EGCSystemMsg_k_EGCMsgMemCachedSet EGCSystemMsg = 202
|
|
||||||
EGCSystemMsg_k_EGCMsgMemCachedDelete EGCSystemMsg = 203
|
|
||||||
EGCSystemMsg_k_EGCMsgMemCachedStats EGCSystemMsg = 204
|
|
||||||
EGCSystemMsg_k_EGCMsgMemCachedStatsResponse EGCSystemMsg = 205
|
|
||||||
EGCSystemMsg_k_EGCMsgSQLStats EGCSystemMsg = 210
|
|
||||||
EGCSystemMsg_k_EGCMsgSQLStatsResponse EGCSystemMsg = 211
|
|
||||||
EGCSystemMsg_k_EGCMsgMasterSetDirectory EGCSystemMsg = 220
|
|
||||||
EGCSystemMsg_k_EGCMsgMasterSetDirectoryResponse EGCSystemMsg = 221
|
|
||||||
EGCSystemMsg_k_EGCMsgMasterSetWebAPIRouting EGCSystemMsg = 222
|
|
||||||
EGCSystemMsg_k_EGCMsgMasterSetWebAPIRoutingResponse EGCSystemMsg = 223
|
|
||||||
EGCSystemMsg_k_EGCMsgMasterSetClientMsgRouting EGCSystemMsg = 224
|
|
||||||
EGCSystemMsg_k_EGCMsgMasterSetClientMsgRoutingResponse EGCSystemMsg = 225
|
|
||||||
EGCSystemMsg_k_EGCMsgSetOptions EGCSystemMsg = 226
|
|
||||||
EGCSystemMsg_k_EGCMsgSetOptionsResponse EGCSystemMsg = 227
|
|
||||||
EGCSystemMsg_k_EGCMsgSystemBase2 EGCSystemMsg = 500
|
|
||||||
EGCSystemMsg_k_EGCMsgGetPurchaseTrustStatus EGCSystemMsg = 501
|
|
||||||
EGCSystemMsg_k_EGCMsgGetPurchaseTrustStatusResponse EGCSystemMsg = 502
|
|
||||||
EGCSystemMsg_k_EGCMsgUpdateSession EGCSystemMsg = 503
|
|
||||||
EGCSystemMsg_k_EGCMsgGCAccountVacStatusChange EGCSystemMsg = 504
|
|
||||||
EGCSystemMsg_k_EGCMsgCheckFriendship EGCSystemMsg = 505
|
|
||||||
EGCSystemMsg_k_EGCMsgCheckFriendshipResponse EGCSystemMsg = 506
|
|
||||||
EGCSystemMsg_k_EGCMsgGetPartnerAccountLink EGCSystemMsg = 507
|
|
||||||
EGCSystemMsg_k_EGCMsgGetPartnerAccountLinkResponse EGCSystemMsg = 508
|
|
||||||
EGCSystemMsg_k_EGCMsgVSReportedSuspiciousActivity EGCSystemMsg = 509
|
|
||||||
EGCSystemMsg_k_EGCMsgDPPartnerMicroTxns EGCSystemMsg = 512
|
|
||||||
EGCSystemMsg_k_EGCMsgDPPartnerMicroTxnsResponse EGCSystemMsg = 513
|
|
||||||
EGCSystemMsg_k_EGCMsgGetIPASN EGCSystemMsg = 514
|
|
||||||
EGCSystemMsg_k_EGCMsgGetIPASNResponse EGCSystemMsg = 515
|
|
||||||
EGCSystemMsg_k_EGCMsgGetAppFriendsList EGCSystemMsg = 516
|
|
||||||
EGCSystemMsg_k_EGCMsgGetAppFriendsListResponse EGCSystemMsg = 517
|
|
||||||
)
|
|
||||||
|
|
||||||
var EGCSystemMsg_name = map[int32]string{
|
|
||||||
0: "k_EGCMsgInvalid",
|
|
||||||
1: "k_EGCMsgMulti",
|
|
||||||
10: "k_EGCMsgGenericReply",
|
|
||||||
50: "k_EGCMsgSystemBase",
|
|
||||||
51: "k_EGCMsgAchievementAwarded",
|
|
||||||
52: "k_EGCMsgConCommand",
|
|
||||||
53: "k_EGCMsgStartPlaying",
|
|
||||||
54: "k_EGCMsgStopPlaying",
|
|
||||||
55: "k_EGCMsgStartGameserver",
|
|
||||||
56: "k_EGCMsgStopGameserver",
|
|
||||||
57: "k_EGCMsgWGRequest",
|
|
||||||
58: "k_EGCMsgWGResponse",
|
|
||||||
59: "k_EGCMsgGetUserGameStatsSchema",
|
|
||||||
60: "k_EGCMsgGetUserGameStatsSchemaResponse",
|
|
||||||
61: "k_EGCMsgGetUserStatsDEPRECATED",
|
|
||||||
62: "k_EGCMsgGetUserStatsResponse",
|
|
||||||
63: "k_EGCMsgAppInfoUpdated",
|
|
||||||
64: "k_EGCMsgValidateSession",
|
|
||||||
65: "k_EGCMsgValidateSessionResponse",
|
|
||||||
66: "k_EGCMsgLookupAccountFromInput",
|
|
||||||
67: "k_EGCMsgSendHTTPRequest",
|
|
||||||
68: "k_EGCMsgSendHTTPRequestResponse",
|
|
||||||
69: "k_EGCMsgPreTestSetup",
|
|
||||||
70: "k_EGCMsgRecordSupportAction",
|
|
||||||
71: "k_EGCMsgGetAccountDetails_DEPRECATED",
|
|
||||||
73: "k_EGCMsgReceiveInterAppMessage",
|
|
||||||
74: "k_EGCMsgFindAccounts",
|
|
||||||
75: "k_EGCMsgPostAlert",
|
|
||||||
76: "k_EGCMsgGetLicenses",
|
|
||||||
77: "k_EGCMsgGetUserStats",
|
|
||||||
78: "k_EGCMsgGetCommands",
|
|
||||||
79: "k_EGCMsgGetCommandsResponse",
|
|
||||||
80: "k_EGCMsgAddFreeLicense",
|
|
||||||
81: "k_EGCMsgAddFreeLicenseResponse",
|
|
||||||
82: "k_EGCMsgGetIPLocation",
|
|
||||||
83: "k_EGCMsgGetIPLocationResponse",
|
|
||||||
84: "k_EGCMsgSystemStatsSchema",
|
|
||||||
85: "k_EGCMsgGetSystemStats",
|
|
||||||
86: "k_EGCMsgGetSystemStatsResponse",
|
|
||||||
87: "k_EGCMsgSendEmail",
|
|
||||||
88: "k_EGCMsgSendEmailResponse",
|
|
||||||
89: "k_EGCMsgGetEmailTemplate",
|
|
||||||
90: "k_EGCMsgGetEmailTemplateResponse",
|
|
||||||
91: "k_EGCMsgGrantGuestPass",
|
|
||||||
92: "k_EGCMsgGrantGuestPassResponse",
|
|
||||||
93: "k_EGCMsgGetAccountDetails",
|
|
||||||
94: "k_EGCMsgGetAccountDetailsResponse",
|
|
||||||
95: "k_EGCMsgGetPersonaNames",
|
|
||||||
96: "k_EGCMsgGetPersonaNamesResponse",
|
|
||||||
97: "k_EGCMsgMultiplexMsg",
|
|
||||||
101: "k_EGCMsgWebAPIRegisterInterfaces",
|
|
||||||
102: "k_EGCMsgWebAPIJobRequest",
|
|
||||||
104: "k_EGCMsgWebAPIJobRequestHttpResponse",
|
|
||||||
105: "k_EGCMsgWebAPIJobRequestForwardResponse",
|
|
||||||
200: "k_EGCMsgMemCachedGet",
|
|
||||||
201: "k_EGCMsgMemCachedGetResponse",
|
|
||||||
202: "k_EGCMsgMemCachedSet",
|
|
||||||
203: "k_EGCMsgMemCachedDelete",
|
|
||||||
204: "k_EGCMsgMemCachedStats",
|
|
||||||
205: "k_EGCMsgMemCachedStatsResponse",
|
|
||||||
210: "k_EGCMsgSQLStats",
|
|
||||||
211: "k_EGCMsgSQLStatsResponse",
|
|
||||||
220: "k_EGCMsgMasterSetDirectory",
|
|
||||||
221: "k_EGCMsgMasterSetDirectoryResponse",
|
|
||||||
222: "k_EGCMsgMasterSetWebAPIRouting",
|
|
||||||
223: "k_EGCMsgMasterSetWebAPIRoutingResponse",
|
|
||||||
224: "k_EGCMsgMasterSetClientMsgRouting",
|
|
||||||
225: "k_EGCMsgMasterSetClientMsgRoutingResponse",
|
|
||||||
226: "k_EGCMsgSetOptions",
|
|
||||||
227: "k_EGCMsgSetOptionsResponse",
|
|
||||||
500: "k_EGCMsgSystemBase2",
|
|
||||||
501: "k_EGCMsgGetPurchaseTrustStatus",
|
|
||||||
502: "k_EGCMsgGetPurchaseTrustStatusResponse",
|
|
||||||
503: "k_EGCMsgUpdateSession",
|
|
||||||
504: "k_EGCMsgGCAccountVacStatusChange",
|
|
||||||
505: "k_EGCMsgCheckFriendship",
|
|
||||||
506: "k_EGCMsgCheckFriendshipResponse",
|
|
||||||
507: "k_EGCMsgGetPartnerAccountLink",
|
|
||||||
508: "k_EGCMsgGetPartnerAccountLinkResponse",
|
|
||||||
509: "k_EGCMsgVSReportedSuspiciousActivity",
|
|
||||||
512: "k_EGCMsgDPPartnerMicroTxns",
|
|
||||||
513: "k_EGCMsgDPPartnerMicroTxnsResponse",
|
|
||||||
514: "k_EGCMsgGetIPASN",
|
|
||||||
515: "k_EGCMsgGetIPASNResponse",
|
|
||||||
516: "k_EGCMsgGetAppFriendsList",
|
|
||||||
517: "k_EGCMsgGetAppFriendsListResponse",
|
|
||||||
}
|
|
||||||
var EGCSystemMsg_value = map[string]int32{
|
|
||||||
"k_EGCMsgInvalid": 0,
|
|
||||||
"k_EGCMsgMulti": 1,
|
|
||||||
"k_EGCMsgGenericReply": 10,
|
|
||||||
"k_EGCMsgSystemBase": 50,
|
|
||||||
"k_EGCMsgAchievementAwarded": 51,
|
|
||||||
"k_EGCMsgConCommand": 52,
|
|
||||||
"k_EGCMsgStartPlaying": 53,
|
|
||||||
"k_EGCMsgStopPlaying": 54,
|
|
||||||
"k_EGCMsgStartGameserver": 55,
|
|
||||||
"k_EGCMsgStopGameserver": 56,
|
|
||||||
"k_EGCMsgWGRequest": 57,
|
|
||||||
"k_EGCMsgWGResponse": 58,
|
|
||||||
"k_EGCMsgGetUserGameStatsSchema": 59,
|
|
||||||
"k_EGCMsgGetUserGameStatsSchemaResponse": 60,
|
|
||||||
"k_EGCMsgGetUserStatsDEPRECATED": 61,
|
|
||||||
"k_EGCMsgGetUserStatsResponse": 62,
|
|
||||||
"k_EGCMsgAppInfoUpdated": 63,
|
|
||||||
"k_EGCMsgValidateSession": 64,
|
|
||||||
"k_EGCMsgValidateSessionResponse": 65,
|
|
||||||
"k_EGCMsgLookupAccountFromInput": 66,
|
|
||||||
"k_EGCMsgSendHTTPRequest": 67,
|
|
||||||
"k_EGCMsgSendHTTPRequestResponse": 68,
|
|
||||||
"k_EGCMsgPreTestSetup": 69,
|
|
||||||
"k_EGCMsgRecordSupportAction": 70,
|
|
||||||
"k_EGCMsgGetAccountDetails_DEPRECATED": 71,
|
|
||||||
"k_EGCMsgReceiveInterAppMessage": 73,
|
|
||||||
"k_EGCMsgFindAccounts": 74,
|
|
||||||
"k_EGCMsgPostAlert": 75,
|
|
||||||
"k_EGCMsgGetLicenses": 76,
|
|
||||||
"k_EGCMsgGetUserStats": 77,
|
|
||||||
"k_EGCMsgGetCommands": 78,
|
|
||||||
"k_EGCMsgGetCommandsResponse": 79,
|
|
||||||
"k_EGCMsgAddFreeLicense": 80,
|
|
||||||
"k_EGCMsgAddFreeLicenseResponse": 81,
|
|
||||||
"k_EGCMsgGetIPLocation": 82,
|
|
||||||
"k_EGCMsgGetIPLocationResponse": 83,
|
|
||||||
"k_EGCMsgSystemStatsSchema": 84,
|
|
||||||
"k_EGCMsgGetSystemStats": 85,
|
|
||||||
"k_EGCMsgGetSystemStatsResponse": 86,
|
|
||||||
"k_EGCMsgSendEmail": 87,
|
|
||||||
"k_EGCMsgSendEmailResponse": 88,
|
|
||||||
"k_EGCMsgGetEmailTemplate": 89,
|
|
||||||
"k_EGCMsgGetEmailTemplateResponse": 90,
|
|
||||||
"k_EGCMsgGrantGuestPass": 91,
|
|
||||||
"k_EGCMsgGrantGuestPassResponse": 92,
|
|
||||||
"k_EGCMsgGetAccountDetails": 93,
|
|
||||||
"k_EGCMsgGetAccountDetailsResponse": 94,
|
|
||||||
"k_EGCMsgGetPersonaNames": 95,
|
|
||||||
"k_EGCMsgGetPersonaNamesResponse": 96,
|
|
||||||
"k_EGCMsgMultiplexMsg": 97,
|
|
||||||
"k_EGCMsgWebAPIRegisterInterfaces": 101,
|
|
||||||
"k_EGCMsgWebAPIJobRequest": 102,
|
|
||||||
"k_EGCMsgWebAPIJobRequestHttpResponse": 104,
|
|
||||||
"k_EGCMsgWebAPIJobRequestForwardResponse": 105,
|
|
||||||
"k_EGCMsgMemCachedGet": 200,
|
|
||||||
"k_EGCMsgMemCachedGetResponse": 201,
|
|
||||||
"k_EGCMsgMemCachedSet": 202,
|
|
||||||
"k_EGCMsgMemCachedDelete": 203,
|
|
||||||
"k_EGCMsgMemCachedStats": 204,
|
|
||||||
"k_EGCMsgMemCachedStatsResponse": 205,
|
|
||||||
"k_EGCMsgSQLStats": 210,
|
|
||||||
"k_EGCMsgSQLStatsResponse": 211,
|
|
||||||
"k_EGCMsgMasterSetDirectory": 220,
|
|
||||||
"k_EGCMsgMasterSetDirectoryResponse": 221,
|
|
||||||
"k_EGCMsgMasterSetWebAPIRouting": 222,
|
|
||||||
"k_EGCMsgMasterSetWebAPIRoutingResponse": 223,
|
|
||||||
"k_EGCMsgMasterSetClientMsgRouting": 224,
|
|
||||||
"k_EGCMsgMasterSetClientMsgRoutingResponse": 225,
|
|
||||||
"k_EGCMsgSetOptions": 226,
|
|
||||||
"k_EGCMsgSetOptionsResponse": 227,
|
|
||||||
"k_EGCMsgSystemBase2": 500,
|
|
||||||
"k_EGCMsgGetPurchaseTrustStatus": 501,
|
|
||||||
"k_EGCMsgGetPurchaseTrustStatusResponse": 502,
|
|
||||||
"k_EGCMsgUpdateSession": 503,
|
|
||||||
"k_EGCMsgGCAccountVacStatusChange": 504,
|
|
||||||
"k_EGCMsgCheckFriendship": 505,
|
|
||||||
"k_EGCMsgCheckFriendshipResponse": 506,
|
|
||||||
"k_EGCMsgGetPartnerAccountLink": 507,
|
|
||||||
"k_EGCMsgGetPartnerAccountLinkResponse": 508,
|
|
||||||
"k_EGCMsgVSReportedSuspiciousActivity": 509,
|
|
||||||
"k_EGCMsgDPPartnerMicroTxns": 512,
|
|
||||||
"k_EGCMsgDPPartnerMicroTxnsResponse": 513,
|
|
||||||
"k_EGCMsgGetIPASN": 514,
|
|
||||||
"k_EGCMsgGetIPASNResponse": 515,
|
|
||||||
"k_EGCMsgGetAppFriendsList": 516,
|
|
||||||
"k_EGCMsgGetAppFriendsListResponse": 517,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x EGCSystemMsg) Enum() *EGCSystemMsg {
|
|
||||||
p := new(EGCSystemMsg)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x EGCSystemMsg) String() string {
|
|
||||||
return proto.EnumName(EGCSystemMsg_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *EGCSystemMsg) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(EGCSystemMsg_value, data, "EGCSystemMsg")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = EGCSystemMsg(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (EGCSystemMsg) EnumDescriptor() ([]byte, []int) { return system_fileDescriptor0, []int{0} }
|
|
||||||
|
|
||||||
type ESOMsg int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
ESOMsg_k_ESOMsg_Create ESOMsg = 21
|
|
||||||
ESOMsg_k_ESOMsg_Update ESOMsg = 22
|
|
||||||
ESOMsg_k_ESOMsg_Destroy ESOMsg = 23
|
|
||||||
ESOMsg_k_ESOMsg_CacheSubscribed ESOMsg = 24
|
|
||||||
ESOMsg_k_ESOMsg_CacheUnsubscribed ESOMsg = 25
|
|
||||||
ESOMsg_k_ESOMsg_UpdateMultiple ESOMsg = 26
|
|
||||||
ESOMsg_k_ESOMsg_CacheSubscriptionRefresh ESOMsg = 28
|
|
||||||
ESOMsg_k_ESOMsg_CacheSubscribedUpToDate ESOMsg = 29
|
|
||||||
)
|
|
||||||
|
|
||||||
var ESOMsg_name = map[int32]string{
|
|
||||||
21: "k_ESOMsg_Create",
|
|
||||||
22: "k_ESOMsg_Update",
|
|
||||||
23: "k_ESOMsg_Destroy",
|
|
||||||
24: "k_ESOMsg_CacheSubscribed",
|
|
||||||
25: "k_ESOMsg_CacheUnsubscribed",
|
|
||||||
26: "k_ESOMsg_UpdateMultiple",
|
|
||||||
28: "k_ESOMsg_CacheSubscriptionRefresh",
|
|
||||||
29: "k_ESOMsg_CacheSubscribedUpToDate",
|
|
||||||
}
|
|
||||||
var ESOMsg_value = map[string]int32{
|
|
||||||
"k_ESOMsg_Create": 21,
|
|
||||||
"k_ESOMsg_Update": 22,
|
|
||||||
"k_ESOMsg_Destroy": 23,
|
|
||||||
"k_ESOMsg_CacheSubscribed": 24,
|
|
||||||
"k_ESOMsg_CacheUnsubscribed": 25,
|
|
||||||
"k_ESOMsg_UpdateMultiple": 26,
|
|
||||||
"k_ESOMsg_CacheSubscriptionRefresh": 28,
|
|
||||||
"k_ESOMsg_CacheSubscribedUpToDate": 29,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x ESOMsg) Enum() *ESOMsg {
|
|
||||||
p := new(ESOMsg)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x ESOMsg) String() string {
|
|
||||||
return proto.EnumName(ESOMsg_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *ESOMsg) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(ESOMsg_value, data, "ESOMsg")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = ESOMsg(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (ESOMsg) EnumDescriptor() ([]byte, []int) { return system_fileDescriptor0, []int{1} }
|
|
||||||
|
|
||||||
type EGCBaseClientMsg int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
EGCBaseClientMsg_k_EMsgGCPingRequest EGCBaseClientMsg = 3001
|
|
||||||
EGCBaseClientMsg_k_EMsgGCPingResponse EGCBaseClientMsg = 3002
|
|
||||||
EGCBaseClientMsg_k_EMsgGCClientWelcome EGCBaseClientMsg = 4004
|
|
||||||
EGCBaseClientMsg_k_EMsgGCServerWelcome EGCBaseClientMsg = 4005
|
|
||||||
EGCBaseClientMsg_k_EMsgGCClientHello EGCBaseClientMsg = 4006
|
|
||||||
EGCBaseClientMsg_k_EMsgGCServerHello EGCBaseClientMsg = 4007
|
|
||||||
EGCBaseClientMsg_k_EMsgGCClientConnectionStatus EGCBaseClientMsg = 4009
|
|
||||||
EGCBaseClientMsg_k_EMsgGCServerConnectionStatus EGCBaseClientMsg = 4010
|
|
||||||
)
|
|
||||||
|
|
||||||
var EGCBaseClientMsg_name = map[int32]string{
|
|
||||||
3001: "k_EMsgGCPingRequest",
|
|
||||||
3002: "k_EMsgGCPingResponse",
|
|
||||||
4004: "k_EMsgGCClientWelcome",
|
|
||||||
4005: "k_EMsgGCServerWelcome",
|
|
||||||
4006: "k_EMsgGCClientHello",
|
|
||||||
4007: "k_EMsgGCServerHello",
|
|
||||||
4009: "k_EMsgGCClientConnectionStatus",
|
|
||||||
4010: "k_EMsgGCServerConnectionStatus",
|
|
||||||
}
|
|
||||||
var EGCBaseClientMsg_value = map[string]int32{
|
|
||||||
"k_EMsgGCPingRequest": 3001,
|
|
||||||
"k_EMsgGCPingResponse": 3002,
|
|
||||||
"k_EMsgGCClientWelcome": 4004,
|
|
||||||
"k_EMsgGCServerWelcome": 4005,
|
|
||||||
"k_EMsgGCClientHello": 4006,
|
|
||||||
"k_EMsgGCServerHello": 4007,
|
|
||||||
"k_EMsgGCClientConnectionStatus": 4009,
|
|
||||||
"k_EMsgGCServerConnectionStatus": 4010,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x EGCBaseClientMsg) Enum() *EGCBaseClientMsg {
|
|
||||||
p := new(EGCBaseClientMsg)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x EGCBaseClientMsg) String() string {
|
|
||||||
return proto.EnumName(EGCBaseClientMsg_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *EGCBaseClientMsg) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(EGCBaseClientMsg_value, data, "EGCBaseClientMsg")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = EGCBaseClientMsg(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (EGCBaseClientMsg) EnumDescriptor() ([]byte, []int) { return system_fileDescriptor0, []int{2} }
|
|
||||||
|
|
||||||
type EGCToGCMsg int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
EGCToGCMsg_k_EGCToGCMsgMasterAck EGCToGCMsg = 150
|
|
||||||
EGCToGCMsg_k_EGCToGCMsgMasterAckResponse EGCToGCMsg = 151
|
|
||||||
EGCToGCMsg_k_EGCToGCMsgRouted EGCToGCMsg = 152
|
|
||||||
EGCToGCMsg_k_EGCToGCMsgRoutedReply EGCToGCMsg = 153
|
|
||||||
EGCToGCMsg_k_EMsgGCUpdateSubGCSessionInfo EGCToGCMsg = 154
|
|
||||||
EGCToGCMsg_k_EMsgGCRequestSubGCSessionInfo EGCToGCMsg = 155
|
|
||||||
EGCToGCMsg_k_EMsgGCRequestSubGCSessionInfoResponse EGCToGCMsg = 156
|
|
||||||
EGCToGCMsg_k_EGCToGCMsgMasterStartupComplete EGCToGCMsg = 157
|
|
||||||
EGCToGCMsg_k_EMsgGCToGCSOCacheSubscribe EGCToGCMsg = 158
|
|
||||||
EGCToGCMsg_k_EMsgGCToGCSOCacheUnsubscribe EGCToGCMsg = 159
|
|
||||||
EGCToGCMsg_k_EMsgGCToGCLoadSessionSOCache EGCToGCMsg = 160
|
|
||||||
EGCToGCMsg_k_EMsgGCToGCLoadSessionSOCacheResponse EGCToGCMsg = 161
|
|
||||||
EGCToGCMsg_k_EMsgGCToGCUpdateSessionStats EGCToGCMsg = 162
|
|
||||||
)
|
|
||||||
|
|
||||||
var EGCToGCMsg_name = map[int32]string{
|
|
||||||
150: "k_EGCToGCMsgMasterAck",
|
|
||||||
151: "k_EGCToGCMsgMasterAckResponse",
|
|
||||||
152: "k_EGCToGCMsgRouted",
|
|
||||||
153: "k_EGCToGCMsgRoutedReply",
|
|
||||||
154: "k_EMsgGCUpdateSubGCSessionInfo",
|
|
||||||
155: "k_EMsgGCRequestSubGCSessionInfo",
|
|
||||||
156: "k_EMsgGCRequestSubGCSessionInfoResponse",
|
|
||||||
157: "k_EGCToGCMsgMasterStartupComplete",
|
|
||||||
158: "k_EMsgGCToGCSOCacheSubscribe",
|
|
||||||
159: "k_EMsgGCToGCSOCacheUnsubscribe",
|
|
||||||
160: "k_EMsgGCToGCLoadSessionSOCache",
|
|
||||||
161: "k_EMsgGCToGCLoadSessionSOCacheResponse",
|
|
||||||
162: "k_EMsgGCToGCUpdateSessionStats",
|
|
||||||
}
|
|
||||||
var EGCToGCMsg_value = map[string]int32{
|
|
||||||
"k_EGCToGCMsgMasterAck": 150,
|
|
||||||
"k_EGCToGCMsgMasterAckResponse": 151,
|
|
||||||
"k_EGCToGCMsgRouted": 152,
|
|
||||||
"k_EGCToGCMsgRoutedReply": 153,
|
|
||||||
"k_EMsgGCUpdateSubGCSessionInfo": 154,
|
|
||||||
"k_EMsgGCRequestSubGCSessionInfo": 155,
|
|
||||||
"k_EMsgGCRequestSubGCSessionInfoResponse": 156,
|
|
||||||
"k_EGCToGCMsgMasterStartupComplete": 157,
|
|
||||||
"k_EMsgGCToGCSOCacheSubscribe": 158,
|
|
||||||
"k_EMsgGCToGCSOCacheUnsubscribe": 159,
|
|
||||||
"k_EMsgGCToGCLoadSessionSOCache": 160,
|
|
||||||
"k_EMsgGCToGCLoadSessionSOCacheResponse": 161,
|
|
||||||
"k_EMsgGCToGCUpdateSessionStats": 162,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x EGCToGCMsg) Enum() *EGCToGCMsg {
|
|
||||||
p := new(EGCToGCMsg)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x EGCToGCMsg) String() string {
|
|
||||||
return proto.EnumName(EGCToGCMsg_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *EGCToGCMsg) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(EGCToGCMsg_value, data, "EGCToGCMsg")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = EGCToGCMsg(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (EGCToGCMsg) EnumDescriptor() ([]byte, []int) { return system_fileDescriptor0, []int{3} }
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterEnum("EGCSystemMsg", EGCSystemMsg_name, EGCSystemMsg_value)
|
|
||||||
proto.RegisterEnum("ESOMsg", ESOMsg_name, ESOMsg_value)
|
|
||||||
proto.RegisterEnum("EGCBaseClientMsg", EGCBaseClientMsg_name, EGCBaseClientMsg_value)
|
|
||||||
proto.RegisterEnum("EGCToGCMsg", EGCToGCMsg_name, EGCToGCMsg_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var system_fileDescriptor0 = []byte{
|
|
||||||
// 1475 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x57, 0x59, 0x73, 0x1b, 0xc5,
|
|
||||||
0x13, 0xcf, 0x96, 0xfc, 0xff, 0x3f, 0x4c, 0x41, 0xd1, 0x99, 0xc4, 0x47, 0x12, 0x27, 0x4a, 0x42,
|
|
||||||
0x0e, 0x62, 0xa8, 0x3c, 0x84, 0xfb, 0x46, 0x91, 0x64, 0x5b, 0x41, 0x8e, 0x15, 0x4b, 0xb6, 0xb9,
|
|
||||||
0xcd, 0x7a, 0x35, 0xb6, 0xb6, 0x2c, 0xed, 0x2c, 0x33, 0xbb, 0x26, 0x7e, 0x0b, 0xd7, 0x57, 0xe0,
|
|
||||||
0xbe, 0x8b, 0xa3, 0xe0, 0x1b, 0xc0, 0x27, 0xe0, 0x7c, 0x81, 0x57, 0xee, 0x7c, 0x01, 0x1e, 0xb8,
|
|
||||||
0x21, 0x55, 0xf4, 0xee, 0xce, 0xce, 0xce, 0x4a, 0xb2, 0x79, 0x93, 0xe6, 0xd7, 0xdd, 0xd3, 0xdd,
|
|
||||||
0xd3, 0xfd, 0xeb, 0x5e, 0x42, 0xd7, 0x1d, 0xb9, 0x25, 0x03, 0xd6, 0xeb, 0xc9, 0x75, 0x79, 0xda,
|
|
||||||
0x17, 0x3c, 0xe0, 0x53, 0x97, 0x47, 0xc9, 0x55, 0xd5, 0x99, 0x72, 0x33, 0x3e, 0x9f, 0x93, 0xeb,
|
|
||||||
0x74, 0x0f, 0xb9, 0x66, 0x63, 0x05, 0x4f, 0xf0, 0x77, 0xcd, 0xdb, 0xb4, 0xbb, 0x6e, 0x1b, 0x76,
|
|
||||||
0xd1, 0xdd, 0xe4, 0xea, 0xf4, 0x70, 0x2e, 0xec, 0x06, 0x2e, 0x58, 0x74, 0x82, 0xec, 0x4d, 0x8f,
|
|
||||||
0x66, 0x98, 0xc7, 0x84, 0xeb, 0x2c, 0x30, 0xbf, 0xbb, 0x05, 0x84, 0x8e, 0x11, 0x9a, 0x22, 0x89,
|
|
||||||
0xd9, 0xb3, 0xb6, 0x64, 0x70, 0x86, 0x1e, 0x22, 0xfb, 0xd3, 0xf3, 0x92, 0xd3, 0x71, 0xd9, 0x26,
|
|
||||||
0xeb, 0x31, 0x2f, 0x28, 0x3d, 0x69, 0x8b, 0x36, 0x6b, 0xc3, 0x8d, 0xa6, 0x5e, 0x99, 0x7b, 0x65,
|
|
||||||
0xde, 0xeb, 0xd9, 0x5e, 0x1b, 0x6e, 0x32, 0x6f, 0x6a, 0x06, 0xb6, 0x08, 0x1a, 0x5d, 0x7b, 0xcb,
|
|
||||||
0xf5, 0xd6, 0xe1, 0x66, 0x3a, 0x4e, 0xf6, 0x64, 0x08, 0xf7, 0x53, 0xe0, 0x16, 0x7a, 0x80, 0x8c,
|
|
||||||
0xe7, 0x54, 0x66, 0xec, 0x1e, 0x93, 0x4c, 0x6c, 0x32, 0x01, 0xb7, 0xd2, 0xfd, 0x64, 0xcc, 0xd4,
|
|
||||||
0x32, 0xb0, 0xdb, 0xe8, 0x28, 0xd9, 0x9d, 0x62, 0xcb, 0x33, 0x0b, 0xec, 0x89, 0x90, 0xc9, 0x00,
|
|
||||||
0x6e, 0x37, 0x5d, 0x8b, 0x8e, 0xa5, 0xcf, 0x3d, 0x0c, 0xe9, 0x0e, 0x7a, 0x94, 0x1c, 0xca, 0x92,
|
|
||||||
0x10, 0x2c, 0xa2, 0x99, 0xc8, 0x1a, 0x5e, 0x19, 0xc8, 0xa6, 0xd3, 0x61, 0x3d, 0x1b, 0xee, 0xa4,
|
|
||||||
0x53, 0xe4, 0xc4, 0xce, 0x32, 0xda, 0xde, 0x5d, 0x43, 0xec, 0xc5, 0x72, 0x95, 0x6a, 0x63, 0xa1,
|
|
||||||
0x5a, 0x2e, 0xb5, 0xaa, 0x15, 0xb8, 0x9b, 0x1e, 0x26, 0x93, 0xc3, 0x64, 0xb4, 0x95, 0x7b, 0xcc,
|
|
||||||
0x00, 0x4b, 0xbe, 0x5f, 0xf3, 0xd6, 0xf8, 0xa2, 0xdf, 0xb6, 0x03, 0x4c, 0xf2, 0xbd, 0x66, 0x66,
|
|
||||||
0x96, 0xa2, 0xc7, 0xc5, 0xe3, 0x26, 0x93, 0xd2, 0xe5, 0x1e, 0xdc, 0x47, 0xaf, 0x25, 0xc5, 0x6d,
|
|
||||||
0x40, 0x6d, 0xbd, 0x64, 0xfa, 0x58, 0xe7, 0x7c, 0x23, 0xf4, 0x4b, 0x8e, 0xc3, 0x43, 0x2f, 0x98,
|
|
||||||
0x16, 0xbc, 0x57, 0xf3, 0xfc, 0x30, 0x80, 0xb3, 0xb9, 0xfc, 0x33, 0xaf, 0x3d, 0xdb, 0x6a, 0x35,
|
|
||||||
0xd2, 0x64, 0x96, 0xcd, 0x5b, 0xfa, 0x40, 0x7d, 0x4b, 0xc5, 0x7c, 0xf4, 0x86, 0x60, 0x2d, 0x04,
|
|
||||||
0x9b, 0x2c, 0x08, 0x7d, 0xa8, 0xd2, 0x22, 0x39, 0x90, 0x22, 0x0b, 0xcc, 0xe1, 0xa2, 0xdd, 0x0c,
|
|
||||||
0x7d, 0x9f, 0x8b, 0xa0, 0xe4, 0x04, 0x51, 0x14, 0xd3, 0xf4, 0x3a, 0x72, 0xcc, 0x48, 0x90, 0xf2,
|
|
||||||
0xae, 0xc2, 0x02, 0xdb, 0xed, 0xca, 0x15, 0x23, 0x95, 0x33, 0x66, 0x28, 0x68, 0x8a, 0xb9, 0x9b,
|
|
||||||
0xac, 0xe6, 0x05, 0x4c, 0x60, 0xd2, 0xe6, 0x30, 0x6c, 0x7b, 0x9d, 0x41, 0xcd, 0x74, 0x64, 0xda,
|
|
||||||
0xf5, 0xda, 0xca, 0x9c, 0x84, 0x73, 0x66, 0xad, 0x34, 0xb8, 0x0c, 0x4a, 0x5d, 0x26, 0x02, 0xb8,
|
|
||||||
0xdf, 0x2c, 0x4a, 0xbc, 0xbe, 0xee, 0x3a, 0x0c, 0x23, 0x92, 0x50, 0xcf, 0x77, 0x4c, 0xf6, 0x70,
|
|
||||||
0x30, 0xd7, 0xa7, 0xa2, 0x2a, 0x5f, 0xc2, 0x79, 0x33, 0x56, 0x03, 0xd0, 0x69, 0x9a, 0xcf, 0x3d,
|
|
||||||
0x75, 0xbb, 0x3d, 0x2d, 0x18, 0x53, 0x17, 0x42, 0xc3, 0x8c, 0x2e, 0x8f, 0x69, 0xfd, 0x0b, 0x74,
|
|
||||||
0x1f, 0x19, 0x35, 0x2e, 0xa8, 0x35, 0xea, 0xdc, 0xb1, 0xe3, 0x34, 0x2e, 0xd0, 0x23, 0xe4, 0xe0,
|
|
||||||
0x50, 0x48, 0x6b, 0x37, 0xe9, 0x41, 0xb2, 0x2f, 0xdf, 0xe9, 0x66, 0xe5, 0xb7, 0x4c, 0xe7, 0xd0,
|
|
||||||
0x82, 0x21, 0x01, 0x8b, 0x7d, 0x95, 0x6e, 0x60, 0xda, 0xfc, 0x92, 0x99, 0xe0, 0xa8, 0x50, 0xaa,
|
|
||||||
0x3d, 0x7c, 0x41, 0x58, 0xce, 0xdd, 0x9a, 0x1e, 0x6b, 0xad, 0x07, 0xe8, 0x24, 0x99, 0x30, 0x2c,
|
|
||||||
0xc7, 0x68, 0x8b, 0xf5, 0xfc, 0x2e, 0x16, 0x33, 0x3c, 0x48, 0x8f, 0x91, 0xc3, 0xdb, 0xa1, 0xda,
|
|
||||||
0xc6, 0x43, 0x39, 0xcf, 0x85, 0xed, 0x05, 0x33, 0x51, 0x75, 0x36, 0x6c, 0x29, 0xe1, 0xe1, 0x9c,
|
|
||||||
0xe7, 0x39, 0x4c, 0xeb, 0x3f, 0x62, 0xba, 0x38, 0x50, 0x82, 0xf0, 0x28, 0x3d, 0x4e, 0x8e, 0x6c,
|
|
||||||
0x0b, 0x6b, 0x2b, 0x8f, 0x99, 0x5d, 0x84, 0x62, 0x0d, 0x26, 0x24, 0xf7, 0xec, 0xf3, 0x11, 0x5d,
|
|
||||||
0xc1, 0x8a, 0xd9, 0x45, 0x7d, 0xa0, 0xb6, 0xf0, 0xb8, 0x59, 0x72, 0x31, 0x6f, 0xfb, 0x5d, 0x76,
|
|
||||||
0x11, 0x7f, 0x83, 0x6d, 0xe6, 0x61, 0x99, 0xad, 0x96, 0x1a, 0xb5, 0x05, 0xb6, 0xee, 0xe2, 0x23,
|
|
||||||
0x88, 0xb8, 0x03, 0xd6, 0x6c, 0x07, 0x2f, 0x61, 0x66, 0x2e, 0x13, 0xa9, 0x73, 0x7c, 0x35, 0x6d,
|
|
||||||
0xe4, 0x35, 0xb3, 0xd1, 0xfa, 0xd1, 0xd9, 0x20, 0xf0, 0xb5, 0x1f, 0x1d, 0x7a, 0x3d, 0x39, 0xb9,
|
|
||||||
0x9d, 0xe4, 0x34, 0x17, 0xd1, 0x04, 0xd0, 0xc2, 0x2e, 0xd6, 0x64, 0xe6, 0x34, 0xeb, 0x95, 0x6d,
|
|
||||||
0x2c, 0xa7, 0x36, 0x86, 0x08, 0x9f, 0x58, 0x58, 0x93, 0x93, 0xc3, 0x20, 0xad, 0xfc, 0xa9, 0x35,
|
|
||||||
0x54, 0x1b, 0xa9, 0x03, 0x3e, 0xb3, 0x30, 0x9a, 0xf1, 0x01, 0xa8, 0xc2, 0xba, 0x0c, 0x0b, 0xe3,
|
|
||||||
0x73, 0x0b, 0xb3, 0x3d, 0x36, 0xa8, 0x18, 0x57, 0xeb, 0x17, 0x16, 0x66, 0xfb, 0xd0, 0x70, 0x50,
|
|
||||||
0x5f, 0xfd, 0xa5, 0x85, 0xf5, 0x0a, 0xba, 0x30, 0x2f, 0xd4, 0x13, 0xdd, 0xaf, 0x2c, 0x2c, 0x86,
|
|
||||||
0x89, 0xfe, 0x63, 0xad, 0xf5, 0xb5, 0x85, 0x3d, 0xae, 0xc7, 0xe2, 0x9c, 0x1d, 0xbd, 0x00, 0x7a,
|
|
||||||
0x5b, 0x71, 0x05, 0x73, 0x02, 0x2e, 0xb6, 0xe0, 0x1b, 0x8b, 0x9e, 0x24, 0x47, 0xb7, 0x17, 0xd0,
|
|
||||||
0x96, 0xbe, 0xcd, 0x3b, 0x99, 0x0a, 0xaa, 0xc7, 0xe5, 0x61, 0x10, 0x4d, 0xc6, 0xef, 0x2c, 0x7c,
|
|
||||||
0x8a, 0x13, 0x3b, 0x0b, 0x69, 0x8b, 0xdf, 0x5b, 0xf4, 0x44, 0x56, 0xa8, 0x5a, 0xb8, 0xdc, 0x75,
|
|
||||||
0x71, 0x6c, 0x47, 0x94, 0xa9, 0x8c, 0xfe, 0x60, 0xd1, 0xd3, 0xe4, 0xd4, 0x7f, 0xca, 0x69, 0xbb,
|
|
||||||
0x3f, 0x5a, 0x48, 0x78, 0xd9, 0x8a, 0xc0, 0x82, 0x79, 0x3f, 0xe2, 0x15, 0x09, 0x3f, 0xe5, 0x92,
|
|
||||||
0x91, 0x01, 0x5a, 0xf3, 0x72, 0xb4, 0x76, 0xec, 0x19, 0x5c, 0x2e, 0xce, 0xc0, 0x2f, 0x05, 0x33,
|
|
||||||
0xfa, 0xa8, 0x21, 0x42, 0xe1, 0x74, 0x10, 0x6a, 0x89, 0x10, 0x47, 0x07, 0xe6, 0x3c, 0x94, 0xf0,
|
|
||||||
0x6b, 0xc1, 0x8c, 0x7e, 0xb8, 0x90, 0xbe, 0xeb, 0xb7, 0x02, 0xb2, 0x80, 0x26, 0xc7, 0x64, 0x80,
|
|
||||||
0xa6, 0x93, 0xf2, 0xf7, 0x02, 0xb6, 0x70, 0xc6, 0x23, 0x65, 0xd5, 0xc1, 0x4b, 0xb6, 0x93, 0x18,
|
|
||||||
0x29, 0x77, 0x6c, 0x0f, 0x87, 0xc7, 0x1f, 0x05, 0xb3, 0xe4, 0xca, 0x1d, 0xe6, 0x6c, 0x4c, 0x0b,
|
|
||||||
0x4c, 0x4a, 0x5b, 0x76, 0x5c, 0x1f, 0xfe, 0x2c, 0x60, 0x13, 0x16, 0xb7, 0x41, 0xb5, 0x1b, 0x7f,
|
|
||||||
0x15, 0x90, 0x70, 0x4c, 0x22, 0x6e, 0xe0, 0x3a, 0x83, 0xeb, 0x96, 0xba, 0xb2, 0xee, 0x7a, 0x1b,
|
|
||||||
0xf0, 0x77, 0x01, 0x97, 0x8c, 0xe3, 0x3b, 0xca, 0x68, 0x7b, 0xff, 0x14, 0xe8, 0xa9, 0xac, 0x6d,
|
|
||||||
0x97, 0x9a, 0xb8, 0xb4, 0xe1, 0xec, 0xc4, 0x62, 0x0e, 0xa5, 0xef, 0x3a, 0x2e, 0x0f, 0x65, 0x34,
|
|
||||||
0x47, 0x37, 0xdd, 0x60, 0x0b, 0xae, 0x14, 0xcc, 0xe7, 0xa8, 0x34, 0x94, 0xd5, 0x39, 0xd7, 0x11,
|
|
||||||
0xbc, 0x75, 0x11, 0xdf, 0xeb, 0xd2, 0x88, 0x59, 0x9b, 0x83, 0x02, 0xfa, 0xd2, 0xa7, 0x46, 0xcc,
|
|
||||||
0xde, 0x88, 0xa7, 0x49, 0xa9, 0x79, 0x1e, 0x9e, 0x1e, 0x31, 0x7b, 0x23, 0x3d, 0xd6, 0x5a, 0xcf,
|
|
||||||
0x8c, 0xe0, 0xca, 0x98, 0xe3, 0x51, 0xdf, 0x57, 0x19, 0xaa, 0x23, 0x55, 0xc1, 0xb3, 0x23, 0x66,
|
|
||||||
0x7d, 0x0e, 0xe0, 0xda, 0xce, 0x73, 0x23, 0x53, 0x3f, 0x5b, 0xe4, 0xff, 0xd5, 0xe6, 0x7c, 0xb6,
|
|
||||||
0xdf, 0xc6, 0xbf, 0x57, 0xca, 0x82, 0x45, 0x53, 0x61, 0x34, 0x77, 0x98, 0x3c, 0x35, 0x8c, 0xd1,
|
|
||||||
0xbd, 0xb1, 0xcb, 0xc9, 0x61, 0x05, 0x99, 0x4a, 0xf0, 0x2d, 0x18, 0x57, 0x94, 0xa8, 0xf4, 0x23,
|
|
||||||
0x1e, 0x68, 0x86, 0xab, 0xd2, 0x11, 0xee, 0x2a, 0xae, 0x57, 0x13, 0x6a, 0xc7, 0x35, 0xd0, 0x45,
|
|
||||||
0x4f, 0x66, 0xf8, 0x3e, 0x45, 0xe9, 0xe6, 0x45, 0x29, 0x2f, 0xc3, 0x7e, 0x35, 0x16, 0x06, 0x4d,
|
|
||||||
0xfb, 0xc9, 0xd8, 0x5d, 0x13, 0x4c, 0x76, 0x60, 0x52, 0x51, 0xf7, 0x50, 0x0f, 0x16, 0xfd, 0x16,
|
|
||||||
0xaf, 0x44, 0xde, 0x1f, 0x9c, 0xba, 0x62, 0x11, 0xc0, 0xcc, 0x44, 0xed, 0xa1, 0x3b, 0x51, 0x75,
|
|
||||||
0x4f, 0x5c, 0xb3, 0x8d, 0xb8, 0x25, 0x13, 0x2a, 0xff, 0x68, 0x5c, 0xd1, 0xa6, 0x81, 0xa8, 0xe4,
|
|
||||||
0x7d, 0x3c, 0xae, 0xda, 0x20, 0x86, 0x12, 0x4b, 0xcb, 0xac, 0xeb, 0xf0, 0x1e, 0x83, 0x77, 0x8a,
|
|
||||||
0x26, 0xd6, 0x8c, 0x77, 0xe8, 0x14, 0x7b, 0xb7, 0x68, 0x5e, 0x96, 0xe8, 0xcd, 0xb2, 0x6e, 0x97,
|
|
||||||
0xc3, 0x7b, 0x39, 0x24, 0xd1, 0x4a, 0x90, 0xf7, 0x8b, 0xaa, 0x89, 0x0d, 0x1d, 0xfc, 0x12, 0xf0,
|
|
||||||
0x58, 0xbc, 0xd9, 0xa9, 0x26, 0xfe, 0x20, 0x27, 0x94, 0xa8, 0x0f, 0x08, 0x7d, 0x58, 0x9c, 0xba,
|
|
||||||
0x5c, 0x20, 0x04, 0xe3, 0x6f, 0xf1, 0xb8, 0x3a, 0x74, 0x2f, 0xab, 0xff, 0x09, 0x4b, 0x95, 0x9c,
|
|
||||||
0x0d, 0x78, 0xde, 0xd2, 0x0d, 0xd6, 0x8f, 0xe9, 0x24, 0xbc, 0x90, 0x31, 0x96, 0x92, 0x89, 0x38,
|
|
||||||
0x0d, 0x1f, 0xf4, 0xc5, 0x6c, 0xa8, 0xe4, 0x80, 0xe4, 0x53, 0xe8, 0x25, 0xcb, 0x74, 0x55, 0x51,
|
|
||||||
0x48, 0xb8, 0x1a, 0x79, 0x1d, 0xf3, 0x48, 0xb4, 0x99, 0xc3, 0xcb, 0x96, 0xa2, 0x81, 0x58, 0x48,
|
|
||||||
0xbd, 0xc8, 0x80, 0xd4, 0x2b, 0x16, 0xbd, 0x21, 0x9e, 0xa1, 0x3b, 0x49, 0x69, 0x7f, 0x5f, 0xcd,
|
|
||||||
0x98, 0x3b, 0x17, 0x53, 0xfc, 0x2d, 0x14, 0xfa, 0xb8, 0x47, 0xfa, 0xf1, 0xd4, 0x7b, 0x2d, 0x9d,
|
|
||||||
0xa8, 0xb1, 0xd5, 0x48, 0xb4, 0x39, 0x9f, 0xaf, 0x28, 0x78, 0x3d, 0x17, 0x83, 0x21, 0x62, 0x14,
|
|
||||||
0x36, 0xbc, 0x31, 0x20, 0x54, 0xe7, 0x76, 0x5b, 0x79, 0xa6, 0xe4, 0xe1, 0xcd, 0x74, 0xf6, 0xec,
|
|
||||||
0x20, 0xa4, 0x23, 0x78, 0x6b, 0xc0, 0x62, 0x8e, 0x81, 0x93, 0xd9, 0xfa, 0xb6, 0x75, 0xf6, 0x7f,
|
|
||||||
0xb3, 0xd6, 0x25, 0x6b, 0xd7, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x05, 0xab, 0xaf, 0x14, 0xda,
|
|
||||||
0x0e, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
188
vendor/github.com/Philipp15b/go-steam/economy/inventory/inventory.go
generated
vendored
188
vendor/github.com/Philipp15b/go-steam/economy/inventory/inventory.go
generated
vendored
@@ -1,188 +0,0 @@
|
|||||||
/*
|
|
||||||
Includes inventory types as used in the trade package
|
|
||||||
*/
|
|
||||||
package inventory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/Philipp15b/go-steam/jsont"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GenericInventory map[uint32]map[uint64]*Inventory
|
|
||||||
|
|
||||||
func NewGenericInventory() GenericInventory {
|
|
||||||
iMap := make(map[uint32]map[uint64]*Inventory)
|
|
||||||
return GenericInventory(iMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get inventory for specified AppId and ContextId
|
|
||||||
func (i *GenericInventory) Get(appId uint32, contextId uint64) (*Inventory, error) {
|
|
||||||
iMap := (map[uint32]map[uint64]*Inventory)(*i)
|
|
||||||
iMap2, ok := iMap[appId]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("inventory for specified appId not found")
|
|
||||||
}
|
|
||||||
inv, ok := iMap2[contextId]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("inventory for specified contextId not found")
|
|
||||||
}
|
|
||||||
return inv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *GenericInventory) Add(appId uint32, contextId uint64, inv *Inventory) {
|
|
||||||
iMap := (map[uint32]map[uint64]*Inventory)(*i)
|
|
||||||
iMap2, ok := iMap[appId]
|
|
||||||
if !ok {
|
|
||||||
iMap2 = make(map[uint64]*Inventory)
|
|
||||||
iMap[appId] = iMap2
|
|
||||||
}
|
|
||||||
iMap2[contextId] = inv
|
|
||||||
}
|
|
||||||
|
|
||||||
type Inventory struct {
|
|
||||||
Items Items `json:"rgInventory"`
|
|
||||||
Currencies Currencies `json:"rgCurrency"`
|
|
||||||
Descriptions Descriptions `json:"rgDescriptions"`
|
|
||||||
AppInfo *AppInfo `json:"rgAppInfo"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Items key is an AssetId
|
|
||||||
type Items map[string]*Item
|
|
||||||
|
|
||||||
func (i *Items) ToMap() map[string]*Item {
|
|
||||||
return (map[string]*Item)(*i)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Items) Get(assetId uint64) (*Item, error) {
|
|
||||||
iMap := (map[string]*Item)(*i)
|
|
||||||
if item, ok := iMap[strconv.FormatUint(assetId, 10)]; ok {
|
|
||||||
return item, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("item not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Items) UnmarshalJSON(data []byte) error {
|
|
||||||
if bytes.Equal(data, []byte("[]")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return json.Unmarshal(data, (*map[string]*Item)(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
type Currencies map[string]*Currency
|
|
||||||
|
|
||||||
func (c *Currencies) ToMap() map[string]*Currency {
|
|
||||||
return (map[string]*Currency)(*c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Currencies) UnmarshalJSON(data []byte) error {
|
|
||||||
if bytes.Equal(data, []byte("[]")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return json.Unmarshal(data, (*map[string]*Currency)(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Descriptions key format is %d_%d, first %d is ClassId, second is InstanceId
|
|
||||||
type Descriptions map[string]*Description
|
|
||||||
|
|
||||||
func (d *Descriptions) ToMap() map[string]*Description {
|
|
||||||
return (map[string]*Description)(*d)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Descriptions) Get(classId uint64, instanceId uint64) (*Description, error) {
|
|
||||||
dMap := (map[string]*Description)(*d)
|
|
||||||
descId := fmt.Sprintf("%v_%v", classId, instanceId)
|
|
||||||
if desc, ok := dMap[descId]; ok {
|
|
||||||
return desc, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("description not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Descriptions) UnmarshalJSON(data []byte) error {
|
|
||||||
if bytes.Equal(data, []byte("[]")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return json.Unmarshal(data, (*map[string]*Description)(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
type Item struct {
|
|
||||||
Id uint64 `json:",string"`
|
|
||||||
ClassId uint64 `json:",string"`
|
|
||||||
InstanceId uint64 `json:",string"`
|
|
||||||
Amount uint64 `json:",string"`
|
|
||||||
Pos uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type Currency struct {
|
|
||||||
Id uint64 `json:",string"`
|
|
||||||
ClassId uint64 `json:",string"`
|
|
||||||
IsCurrency bool `json:"is_currency"`
|
|
||||||
Pos uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type Description struct {
|
|
||||||
AppId uint32 `json:",string"`
|
|
||||||
ClassId uint64 `json:",string"`
|
|
||||||
InstanceId uint64 `json:",string"`
|
|
||||||
|
|
||||||
IconUrl string `json:"icon_url"`
|
|
||||||
IconUrlLarge string `json:"icon_url_large"`
|
|
||||||
IconDragUrl string `json:"icon_drag_url"`
|
|
||||||
|
|
||||||
Name string
|
|
||||||
MarketName string `json:"market_name"`
|
|
||||||
MarketHashName string `json:"market_hash_name"`
|
|
||||||
|
|
||||||
// Colors in hex, for example `B2B2B2`
|
|
||||||
NameColor string `json:"name_color"`
|
|
||||||
BackgroundColor string `json:"background_color"`
|
|
||||||
|
|
||||||
Type string
|
|
||||||
|
|
||||||
Tradable jsont.UintBool
|
|
||||||
Marketable jsont.UintBool
|
|
||||||
Commodity jsont.UintBool
|
|
||||||
MarketTradableRestriction uint32 `json:"market_tradable_restriction,string"`
|
|
||||||
|
|
||||||
Descriptions DescriptionLines
|
|
||||||
Actions []*Action
|
|
||||||
// Application-specific data, like "def_index" and "quality" for TF2
|
|
||||||
AppData map[string]string
|
|
||||||
Tags []*Tag
|
|
||||||
}
|
|
||||||
|
|
||||||
type DescriptionLines []*DescriptionLine
|
|
||||||
|
|
||||||
func (d *DescriptionLines) UnmarshalJSON(data []byte) error {
|
|
||||||
if bytes.Equal(data, []byte(`""`)) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return json.Unmarshal(data, (*[]*DescriptionLine)(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
type DescriptionLine struct {
|
|
||||||
Value string
|
|
||||||
Type *string // Is `html` for HTML descriptions
|
|
||||||
Color *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Action struct {
|
|
||||||
Name string
|
|
||||||
Link string
|
|
||||||
}
|
|
||||||
|
|
||||||
type AppInfo struct {
|
|
||||||
AppId uint32
|
|
||||||
Name string
|
|
||||||
Icon string
|
|
||||||
Link string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tag struct {
|
|
||||||
InternalName string `json:internal_name`
|
|
||||||
Name string
|
|
||||||
Category string
|
|
||||||
CategoryName string `json:category_name`
|
|
||||||
}
|
|
||||||
79
vendor/github.com/Philipp15b/go-steam/economy/inventory/inventory_apps.go
generated
vendored
79
vendor/github.com/Philipp15b/go-steam/economy/inventory/inventory_apps.go
generated
vendored
@@ -1,79 +0,0 @@
|
|||||||
package inventory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/Philipp15b/go-steam/steamid"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type InventoryApps map[string]*InventoryApp
|
|
||||||
|
|
||||||
func (i *InventoryApps) Get(appId uint32) (*InventoryApp, error) {
|
|
||||||
iMap := (map[string]*InventoryApp)(*i)
|
|
||||||
if inventoryApp, ok := iMap[strconv.FormatUint(uint64(appId), 10)]; ok {
|
|
||||||
return inventoryApp, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("inventory app not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *InventoryApps) ToMap() map[string]*InventoryApp {
|
|
||||||
return (map[string]*InventoryApp)(*i)
|
|
||||||
}
|
|
||||||
|
|
||||||
type InventoryApp struct {
|
|
||||||
AppId uint32
|
|
||||||
Name string
|
|
||||||
Icon string
|
|
||||||
Link string
|
|
||||||
AssetCount uint32 `json:"asset_count"`
|
|
||||||
InventoryLogo string `json:"inventory_logo"`
|
|
||||||
TradePermissions string `json:"trade_permissions"`
|
|
||||||
Contexts Contexts `json:"rgContexts"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Contexts map[string]*Context
|
|
||||||
|
|
||||||
func (c *Contexts) Get(contextId uint64) (*Context, error) {
|
|
||||||
cMap := (map[string]*Context)(*c)
|
|
||||||
if context, ok := cMap[strconv.FormatUint(contextId, 10)]; ok {
|
|
||||||
return context, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("context not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Contexts) ToMap() map[string]*Context {
|
|
||||||
return (map[string]*Context)(*c)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Context struct {
|
|
||||||
ContextId uint64 `json:"id,string"`
|
|
||||||
AssetCount uint32 `json:"asset_count"`
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetInventoryApps(client *http.Client, steamId steamid.SteamId) (InventoryApps, error) {
|
|
||||||
resp, err := http.Get("http://steamcommunity.com/profiles/" + steamId.ToString() + "/inventory/")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
respBody, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
reg := regexp.MustCompile("var g_rgAppContextData = (.*?);")
|
|
||||||
inventoryAppsMatches := reg.FindSubmatch(respBody)
|
|
||||||
if inventoryAppsMatches == nil {
|
|
||||||
return nil, fmt.Errorf("profile inventory not found in steam response")
|
|
||||||
}
|
|
||||||
var inventoryApps InventoryApps
|
|
||||||
if err = json.Unmarshal(inventoryAppsMatches[1], &inventoryApps); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return inventoryApps, nil
|
|
||||||
}
|
|
||||||
28
vendor/github.com/Philipp15b/go-steam/economy/inventory/own.go
generated
vendored
28
vendor/github.com/Philipp15b/go-steam/economy/inventory/own.go
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
package inventory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetPartialOwnInventory(client *http.Client, contextId uint64, appId uint32, start *uint) (*PartialInventory, error) {
|
|
||||||
// TODO: the "trading" parameter can be left off to return non-tradable items too
|
|
||||||
url := fmt.Sprintf("http://steamcommunity.com/my/inventory/json/%d/%d?trading=1", appId, contextId)
|
|
||||||
if start != nil {
|
|
||||||
url += "&start=" + strconv.FormatUint(uint64(*start), 10)
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return DoInventoryRequest(client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetOwnInventory(client *http.Client, contextId uint64, appId uint32) (*Inventory, error) {
|
|
||||||
return GetFullInventory(func() (*PartialInventory, error) {
|
|
||||||
return GetPartialOwnInventory(client, contextId, appId, nil)
|
|
||||||
}, func(start uint) (*PartialInventory, error) {
|
|
||||||
return GetPartialOwnInventory(client, contextId, appId, &start)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
91
vendor/github.com/Philipp15b/go-steam/economy/inventory/partial.go
generated
vendored
91
vendor/github.com/Philipp15b/go-steam/economy/inventory/partial.go
generated
vendored
@@ -1,91 +0,0 @@
|
|||||||
package inventory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A partial inventory as sent by the Steam API.
|
|
||||||
type PartialInventory struct {
|
|
||||||
Success bool
|
|
||||||
Error string
|
|
||||||
Inventory
|
|
||||||
More bool
|
|
||||||
MoreStart MoreStart `json:"more_start"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MoreStart uint
|
|
||||||
|
|
||||||
func (m *MoreStart) UnmarshalJSON(data []byte) error {
|
|
||||||
if bytes.Equal(data, []byte("false")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return json.Unmarshal(data, (*uint)(m))
|
|
||||||
}
|
|
||||||
|
|
||||||
func DoInventoryRequest(client *http.Client, req *http.Request) (*PartialInventory, error) {
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
inv := new(PartialInventory)
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(inv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return inv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFullInventory(getFirst func() (*PartialInventory, error), getNext func(start uint) (*PartialInventory, error)) (*Inventory, error) {
|
|
||||||
first, err := getFirst()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !first.Success {
|
|
||||||
return nil, errors.New("GetFullInventory API call failed: " + first.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := &first.Inventory
|
|
||||||
var next *PartialInventory
|
|
||||||
for latest := first; latest.More; latest = next {
|
|
||||||
next, err := getNext(uint(latest.MoreStart))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !next.Success {
|
|
||||||
return nil, errors.New("GetFullInventory API call failed: " + next.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
result = Merge(result, &next.Inventory)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merges the given Inventory into a single Inventory.
|
|
||||||
// The given slice must have at least one element. The first element of the slice is used
|
|
||||||
// and modified.
|
|
||||||
func Merge(p ...*Inventory) *Inventory {
|
|
||||||
inv := p[0]
|
|
||||||
for idx, i := range p {
|
|
||||||
if idx == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value := range i.Items {
|
|
||||||
inv.Items[key] = value
|
|
||||||
}
|
|
||||||
for key, value := range i.Descriptions {
|
|
||||||
inv.Descriptions[key] = value
|
|
||||||
}
|
|
||||||
for key, value := range i.Currencies {
|
|
||||||
inv.Currencies[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return inv
|
|
||||||
}
|
|
||||||
295
vendor/github.com/Philipp15b/go-steam/generator/generator.go
generated
vendored
295
vendor/github.com/Philipp15b/go-steam/generator/generator.go
generated
vendored
@@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
This program generates the protobuf and SteamLanguage files from the SteamKit data.
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var printCommands = false
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
args := strings.Join(os.Args[1:], " ")
|
|
||||||
|
|
||||||
found := false
|
|
||||||
if strings.Contains(args, "clean") {
|
|
||||||
clean()
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
if strings.Contains(args, "steamlang") {
|
|
||||||
buildSteamLanguage()
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
if strings.Contains(args, "proto") {
|
|
||||||
buildProto()
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
os.Stderr.WriteString("Invalid target!\nAvailable targets: clean, proto, steamlang\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func clean() {
|
|
||||||
print("# Cleaning")
|
|
||||||
cleanGlob("../protocol/**/*.pb.go")
|
|
||||||
cleanGlob("../tf2/protocol/**/*.pb.go")
|
|
||||||
cleanGlob("../dota/protocol/**/*.pb.go")
|
|
||||||
|
|
||||||
os.Remove("../protocol/steamlang/enums.go")
|
|
||||||
os.Remove("../protocol/steamlang/messages.go")
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanGlob(pattern string) {
|
|
||||||
protos, _ := filepath.Glob(pattern)
|
|
||||||
for _, proto := range protos {
|
|
||||||
err := os.Remove(proto)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildSteamLanguage() {
|
|
||||||
print("# Building Steam Language")
|
|
||||||
exePath := "./GoSteamLanguageGenerator/bin/Debug/GoSteamLanguageGenerator.exe"
|
|
||||||
|
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
execute("mono", exePath, "./SteamKit", "../protocol/steamlang")
|
|
||||||
} else {
|
|
||||||
execute(exePath, "./SteamKit", "../protocol/steamlang")
|
|
||||||
}
|
|
||||||
execute("gofmt", "-w", "../protocol/steamlang/enums.go", "../protocol/steamlang/messages.go")
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildProto() {
|
|
||||||
print("# Building Protobufs")
|
|
||||||
|
|
||||||
buildProtoMap("steamclient", clientProtoFiles, "../protocol/protobuf")
|
|
||||||
buildProtoMap("tf", tf2ProtoFiles, "../tf2/protocol/protobuf")
|
|
||||||
buildProtoMap("dota", dotaProtoFiles, "../dota/protocol/protobuf")
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildProtoMap(srcSubdir string, files map[string]string, outDir string) {
|
|
||||||
os.MkdirAll(outDir, os.ModePerm)
|
|
||||||
for proto, out := range files {
|
|
||||||
full := filepath.Join(outDir, out)
|
|
||||||
compileProto("SteamKit/Resources/Protobufs", srcSubdir, proto, full)
|
|
||||||
fixProto(full)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maps the proto files to their target files.
|
|
||||||
// See `SteamKit/Resources/Protobufs/steamclient/generate-base.bat` for reference.
|
|
||||||
var clientProtoFiles = map[string]string{
|
|
||||||
"steammessages_base.proto": "base.pb.go",
|
|
||||||
"encrypted_app_ticket.proto": "app_ticket.pb.go",
|
|
||||||
|
|
||||||
"steammessages_clientserver.proto": "client_server.pb.go",
|
|
||||||
"steammessages_clientserver_2.proto": "client_server_2.pb.go",
|
|
||||||
|
|
||||||
"content_manifest.proto": "content_manifest.pb.go",
|
|
||||||
|
|
||||||
"steammessages_unified_base.steamclient.proto": "unified/base.pb.go",
|
|
||||||
"steammessages_cloud.steamclient.proto": "unified/cloud.pb.go",
|
|
||||||
"steammessages_credentials.steamclient.proto": "unified/credentials.pb.go",
|
|
||||||
"steammessages_deviceauth.steamclient.proto": "unified/deviceauth.pb.go",
|
|
||||||
"steammessages_gamenotifications.steamclient.proto": "unified/gamenotifications.pb.go",
|
|
||||||
"steammessages_offline.steamclient.proto": "unified/offline.pb.go",
|
|
||||||
"steammessages_parental.steamclient.proto": "unified/parental.pb.go",
|
|
||||||
"steammessages_partnerapps.steamclient.proto": "unified/partnerapps.pb.go",
|
|
||||||
"steammessages_player.steamclient.proto": "unified/player.pb.go",
|
|
||||||
"steammessages_publishedfile.steamclient.proto": "unified/publishedfile.pb.go",
|
|
||||||
}
|
|
||||||
|
|
||||||
var tf2ProtoFiles = map[string]string{
|
|
||||||
"base_gcmessages.proto": "base.pb.go",
|
|
||||||
"econ_gcmessages.proto": "econ.pb.go",
|
|
||||||
"gcsdk_gcmessages.proto": "gcsdk.pb.go",
|
|
||||||
"tf_gcmessages.proto": "tf.pb.go",
|
|
||||||
"gcsystemmsgs.proto": "system.pb.go",
|
|
||||||
}
|
|
||||||
|
|
||||||
var dotaProtoFiles = map[string]string{
|
|
||||||
"base_gcmessages.proto": "base.pb.go",
|
|
||||||
"econ_gcmessages.proto": "econ.pb.go",
|
|
||||||
"gcsdk_gcmessages.proto": "gcsdk.pb.go",
|
|
||||||
"dota_gcmessages_common.proto": "dota_common.pb.go",
|
|
||||||
"dota_gcmessages_client.proto": "dota_client.pb.go",
|
|
||||||
"dota_gcmessages_client_fantasy.proto": "dota_client_fantasy.pb.go",
|
|
||||||
"gcsystemmsgs.proto": "system.pb.go",
|
|
||||||
}
|
|
||||||
|
|
||||||
func compileProto(srcBase, srcSubdir, proto, target string) {
|
|
||||||
outDir, _ := filepath.Split(target)
|
|
||||||
err := os.MkdirAll(outDir, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
execute("protoc", "--go_out="+outDir, "-I="+srcBase+"/"+srcSubdir, "-I="+srcBase, filepath.Join(srcBase, srcSubdir, proto))
|
|
||||||
out := strings.Replace(filepath.Join(outDir, proto), ".proto", ".pb.go", 1)
|
|
||||||
err = forceRename(out, target)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func forceRename(from, to string) error {
|
|
||||||
if from != to {
|
|
||||||
os.Remove(to)
|
|
||||||
}
|
|
||||||
return os.Rename(from, to)
|
|
||||||
}
|
|
||||||
|
|
||||||
var pkgRegex = regexp.MustCompile(`(package \w+)`)
|
|
||||||
var pkgCommentRegex = regexp.MustCompile(`(?s)(\/\*.*?\*\/\n)package`)
|
|
||||||
var unusedImportCommentRegex = regexp.MustCompile("// discarding unused import .*\n")
|
|
||||||
var fileDescriptorVarRegex = regexp.MustCompile(`fileDescriptor\d+`)
|
|
||||||
|
|
||||||
func fixProto(path string) {
|
|
||||||
// goprotobuf is really bad at dependencies, so we must fix them manually...
|
|
||||||
// It tries to load each dependency of a file as a seperate package (but in a very, very wrong way).
|
|
||||||
// Because we want some files in the same package, we'll remove those imports to local files.
|
|
||||||
|
|
||||||
file, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
f, err := parser.ParseFile(fset, path, file, parser.ImportsOnly)
|
|
||||||
if err != nil {
|
|
||||||
panic("Error parsing " + path + ": " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
importsToRemove := make([]*ast.ImportSpec, 0)
|
|
||||||
for _, i := range f.Imports {
|
|
||||||
// We remove all local imports
|
|
||||||
if i.Path.Value == "\".\"" {
|
|
||||||
importsToRemove = append(importsToRemove, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, itr := range importsToRemove {
|
|
||||||
// remove the package name from all types
|
|
||||||
file = bytes.Replace(file, []byte(itr.Name.Name+"."), []byte{}, -1)
|
|
||||||
// and remove the import itself
|
|
||||||
file = bytes.Replace(file, []byte(fmt.Sprintf("import %v %v\n", itr.Name.Name, itr.Path.Value)), []byte{}, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the package comment because it just includes a list of all messages and
|
|
||||||
// collides not only with the other compiled protobuf files, but also our own documentation.
|
|
||||||
file = cutAllSubmatch(pkgCommentRegex, file, 1)
|
|
||||||
|
|
||||||
// remove warnings
|
|
||||||
file = unusedImportCommentRegex.ReplaceAllLiteral(file, []byte{})
|
|
||||||
|
|
||||||
// fix the package name
|
|
||||||
file = pkgRegex.ReplaceAll(file, []byte("package "+inferPackageName(path)))
|
|
||||||
|
|
||||||
// fix the google dependency;
|
|
||||||
// we just reuse the one from protoc-gen-go
|
|
||||||
file = bytes.Replace(file, []byte("google/protobuf"), []byte("github.com/golang/protobuf/protoc-gen-go/descriptor"), -1)
|
|
||||||
|
|
||||||
// we need to prefix local variables created by protoc-gen-go so that they don't clash with others in the same package
|
|
||||||
filename := strings.Split(filepath.Base(path), ".")[0]
|
|
||||||
file = fileDescriptorVarRegex.ReplaceAllFunc(file, func(match []byte) []byte {
|
|
||||||
return []byte(filename + "_" + string(match))
|
|
||||||
})
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(path, file, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func inferPackageName(path string) string {
|
|
||||||
pieces := strings.Split(path, string(filepath.Separator))
|
|
||||||
return pieces[len(pieces)-2]
|
|
||||||
}
|
|
||||||
|
|
||||||
func cutAllSubmatch(r *regexp.Regexp, b []byte, n int) []byte {
|
|
||||||
i := r.FindSubmatchIndex(b)
|
|
||||||
return bytesCut(b, i[2*n], i[2*n+1])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes the given section from the byte array
|
|
||||||
func bytesCut(b []byte, from, to int) []byte {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
buf.Write(b[:from])
|
|
||||||
buf.Write(b[to:])
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func print(text string) { os.Stdout.WriteString(text + "\n") }
|
|
||||||
|
|
||||||
func printerr(text string) { os.Stderr.WriteString(text + "\n") }
|
|
||||||
|
|
||||||
// This writer appends a "> " after every newline so that the outpout appears quoted.
|
|
||||||
type QuotedWriter struct {
|
|
||||||
w io.Writer
|
|
||||||
started bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewQuotedWriter(w io.Writer) *QuotedWriter {
|
|
||||||
return &QuotedWriter{w, false}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *QuotedWriter) Write(p []byte) (n int, err error) {
|
|
||||||
if !w.started {
|
|
||||||
_, err = w.w.Write([]byte("> "))
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
w.started = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, c := range p {
|
|
||||||
if c == '\n' {
|
|
||||||
nw, err := w.w.Write(p[n : i+1])
|
|
||||||
n += nw
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.w.Write([]byte("> "))
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if n != len(p) {
|
|
||||||
nw, err := w.w.Write(p[n:len(p)])
|
|
||||||
n += nw
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func execute(command string, args ...string) {
|
|
||||||
if printCommands {
|
|
||||||
print(command + " " + strings.Join(args, " "))
|
|
||||||
}
|
|
||||||
cmd := exec.Command(command, args...)
|
|
||||||
cmd.Stdout = NewQuotedWriter(os.Stdout)
|
|
||||||
cmd.Stderr = NewQuotedWriter(os.Stderr)
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
printerr(err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
210
vendor/github.com/Philipp15b/go-steam/gsbot/gsbot.go
generated
vendored
210
vendor/github.com/Philipp15b/go-steam/gsbot/gsbot.go
generated
vendored
@@ -1,210 +0,0 @@
|
|||||||
// The GsBot package contains some useful utilites for working with the
|
|
||||||
// steam package. It implements authentication with sentries, server lists and
|
|
||||||
// logging messages and events.
|
|
||||||
//
|
|
||||||
// Every module is optional and requires an instance of the GsBot struct.
|
|
||||||
// Should a module have a `HandlePacket` method, you must register it with the
|
|
||||||
// steam.Client with `RegisterPacketHandler`. Any module with a `HandleEvent`
|
|
||||||
// method must be integrated into your event loop and should be called for each
|
|
||||||
// event you receive.
|
|
||||||
package gsbot
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"math/rand"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"reflect"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Philipp15b/go-steam"
|
|
||||||
"github.com/Philipp15b/go-steam/netutil"
|
|
||||||
"github.com/Philipp15b/go-steam/protocol"
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Base structure holding common data among GsBot modules.
|
|
||||||
type GsBot struct {
|
|
||||||
Client *steam.Client
|
|
||||||
Log *log.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a new GsBot with a new steam.Client where logs are written to stdout.
|
|
||||||
func Default() *GsBot {
|
|
||||||
return &GsBot{
|
|
||||||
steam.NewClient(),
|
|
||||||
log.New(os.Stdout, "", 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This module handles authentication. It logs on automatically after a ConnectedEvent
|
|
||||||
// and saves the sentry data to a file which is also used for logon if available.
|
|
||||||
// If you're logging on for the first time Steam may require an authcode. You can then
|
|
||||||
// connect again with the new logon details.
|
|
||||||
type Auth struct {
|
|
||||||
bot *GsBot
|
|
||||||
details *LogOnDetails
|
|
||||||
sentryPath string
|
|
||||||
machineAuthHash []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAuth(bot *GsBot, details *LogOnDetails, sentryPath string) *Auth {
|
|
||||||
return &Auth{
|
|
||||||
bot: bot,
|
|
||||||
details: details,
|
|
||||||
sentryPath: sentryPath,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogOnDetails struct {
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
AuthCode string
|
|
||||||
TwoFactorCode string
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called automatically after every ConnectedEvent, but must be called once again manually
|
|
||||||
// with an authcode if Steam requires it when logging on for the first time.
|
|
||||||
func (a *Auth) LogOn(details *LogOnDetails) {
|
|
||||||
a.details = details
|
|
||||||
sentry, err := ioutil.ReadFile(a.sentryPath)
|
|
||||||
if err != nil {
|
|
||||||
a.bot.Log.Printf("Error loading sentry file from path %v - This is normal if you're logging in for the first time.\n", a.sentryPath)
|
|
||||||
}
|
|
||||||
a.bot.Client.Auth.LogOn(&steam.LogOnDetails{
|
|
||||||
Username: details.Username,
|
|
||||||
Password: details.Password,
|
|
||||||
SentryFileHash: sentry,
|
|
||||||
AuthCode: details.AuthCode,
|
|
||||||
TwoFactorCode: details.TwoFactorCode,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Auth) HandleEvent(event interface{}) {
|
|
||||||
switch e := event.(type) {
|
|
||||||
case *steam.ConnectedEvent:
|
|
||||||
a.LogOn(a.details)
|
|
||||||
case *steam.LoggedOnEvent:
|
|
||||||
a.bot.Log.Printf("Logged on (%v) with SteamId %v and account flags %v", e.Result, e.ClientSteamId, e.AccountFlags)
|
|
||||||
case *steam.MachineAuthUpdateEvent:
|
|
||||||
a.machineAuthHash = e.Hash
|
|
||||||
err := ioutil.WriteFile(a.sentryPath, e.Hash, 0666)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This module saves the server list from ClientCMListEvent and uses
|
|
||||||
// it when you call `Connect()`.
|
|
||||||
type ServerList struct {
|
|
||||||
bot *GsBot
|
|
||||||
listPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewServerList(bot *GsBot, listPath string) *ServerList {
|
|
||||||
return &ServerList{
|
|
||||||
bot,
|
|
||||||
listPath,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerList) HandleEvent(event interface{}) {
|
|
||||||
switch e := event.(type) {
|
|
||||||
case *steam.ClientCMListEvent:
|
|
||||||
d, err := json.Marshal(e.Addresses)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile(s.listPath, d, 0666)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerList) Connect() (bool, error) {
|
|
||||||
return s.ConnectBind(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerList) ConnectBind(laddr *net.TCPAddr) (bool, error) {
|
|
||||||
d, err := ioutil.ReadFile(s.listPath)
|
|
||||||
if err != nil {
|
|
||||||
s.bot.Log.Println("Connecting to random server.")
|
|
||||||
s.bot.Client.Connect()
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
var addrs []*netutil.PortAddr
|
|
||||||
err = json.Unmarshal(d, &addrs)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
raddr := addrs[rand.Intn(len(addrs))]
|
|
||||||
s.bot.Log.Printf("Connecting to %v from server list\n", raddr)
|
|
||||||
s.bot.Client.ConnectToBind(raddr, laddr)
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// This module logs incoming packets and events to a directory.
|
|
||||||
type Debug struct {
|
|
||||||
packetId, eventId uint64
|
|
||||||
bot *GsBot
|
|
||||||
base string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDebug(bot *GsBot, base string) (*Debug, error) {
|
|
||||||
base = path.Join(base, fmt.Sprint(time.Now().Unix()))
|
|
||||||
err := os.MkdirAll(path.Join(base, "events"), 0700)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = os.MkdirAll(path.Join(base, "packets"), 0700)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Debug{
|
|
||||||
0, 0,
|
|
||||||
bot,
|
|
||||||
base,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Debug) HandlePacket(packet *protocol.Packet) {
|
|
||||||
d.packetId++
|
|
||||||
name := path.Join(d.base, "packets", fmt.Sprintf("%d_%d_%s", time.Now().Unix(), d.packetId, packet.EMsg))
|
|
||||||
|
|
||||||
text := packet.String() + "\n\n" + hex.Dump(packet.Data)
|
|
||||||
err := ioutil.WriteFile(name+".txt", []byte(text), 0666)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(name+".bin", packet.Data, 0666)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Debug) HandleEvent(event interface{}) {
|
|
||||||
d.eventId++
|
|
||||||
name := fmt.Sprintf("%d_%d_%s.txt", time.Now().Unix(), d.eventId, name(event))
|
|
||||||
err := ioutil.WriteFile(path.Join(d.base, "events", name), []byte(spew.Sdump(event)), 0666)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func name(obj interface{}) string {
|
|
||||||
val := reflect.ValueOf(obj)
|
|
||||||
ind := reflect.Indirect(val)
|
|
||||||
if ind.IsValid() {
|
|
||||||
return ind.Type().Name()
|
|
||||||
} else {
|
|
||||||
return val.Type().Name()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
56
vendor/github.com/Philipp15b/go-steam/gsbot/gsbot/gsbot.go
generated
vendored
56
vendor/github.com/Philipp15b/go-steam/gsbot/gsbot/gsbot.go
generated
vendored
@@ -1,56 +0,0 @@
|
|||||||
// A simple example that uses the modules from the gsbot package and go-steam to log on
|
|
||||||
// to the Steam network.
|
|
||||||
//
|
|
||||||
// The command expects log on data, optionally with an auth code:
|
|
||||||
//
|
|
||||||
// gsbot [username] [password]
|
|
||||||
// gsbot [username] [password] [authcode]
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/Philipp15b/go-steam"
|
|
||||||
"github.com/Philipp15b/go-steam/gsbot"
|
|
||||||
"github.com/Philipp15b/go-steam/protocol/steamlang"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) < 3 {
|
|
||||||
fmt.Println("gsbot example\nusage: \n\tgsbot [username] [password] [authcode]")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
authcode := ""
|
|
||||||
if len(os.Args) > 3 {
|
|
||||||
authcode = os.Args[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
bot := gsbot.Default()
|
|
||||||
client := bot.Client
|
|
||||||
auth := gsbot.NewAuth(bot, &gsbot.LogOnDetails{
|
|
||||||
os.Args[1],
|
|
||||||
os.Args[2],
|
|
||||||
authcode,
|
|
||||||
}, "sentry.bin")
|
|
||||||
debug, err := gsbot.NewDebug(bot, "debug")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
client.RegisterPacketHandler(debug)
|
|
||||||
serverList := gsbot.NewServerList(bot, "serverlist.json")
|
|
||||||
serverList.Connect()
|
|
||||||
|
|
||||||
for event := range client.Events() {
|
|
||||||
auth.HandleEvent(event)
|
|
||||||
debug.HandleEvent(event)
|
|
||||||
serverList.HandleEvent(event)
|
|
||||||
|
|
||||||
switch e := event.(type) {
|
|
||||||
case error:
|
|
||||||
fmt.Printf("Error: %v", e)
|
|
||||||
case *steam.LoggedOnEvent:
|
|
||||||
client.Social.SetPersonaState(steamlang.EPersonaState_Online)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
19
vendor/github.com/Philipp15b/go-steam/jsont/jsont.go
generated
vendored
19
vendor/github.com/Philipp15b/go-steam/jsont/jsont.go
generated
vendored
@@ -1,19 +0,0 @@
|
|||||||
// Includes helper types for working with JSON data
|
|
||||||
package jsont
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A boolean value that can be unmarshaled from a number in JSON.
|
|
||||||
type UintBool bool
|
|
||||||
|
|
||||||
func (u *UintBool) UnmarshalJSON(data []byte) error {
|
|
||||||
var n uint
|
|
||||||
err := json.Unmarshal(data, &n)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*u = n != 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
141
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/base.pb.go
generated
vendored
141
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/base.pb.go
generated
vendored
@@ -1,141 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go.
|
|
||||||
// source: steammessages_unified_base.steamclient.proto
|
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
package unified
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import fmt "fmt"
|
|
||||||
import math "math"
|
|
||||||
import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
type EProtoExecutionSite int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
EProtoExecutionSite_k_EProtoExecutionSiteUnknown EProtoExecutionSite = 0
|
|
||||||
EProtoExecutionSite_k_EProtoExecutionSiteSteamClient EProtoExecutionSite = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var EProtoExecutionSite_name = map[int32]string{
|
|
||||||
0: "k_EProtoExecutionSiteUnknown",
|
|
||||||
2: "k_EProtoExecutionSiteSteamClient",
|
|
||||||
}
|
|
||||||
var EProtoExecutionSite_value = map[string]int32{
|
|
||||||
"k_EProtoExecutionSiteUnknown": 0,
|
|
||||||
"k_EProtoExecutionSiteSteamClient": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x EProtoExecutionSite) Enum() *EProtoExecutionSite {
|
|
||||||
p := new(EProtoExecutionSite)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x EProtoExecutionSite) String() string {
|
|
||||||
return proto.EnumName(EProtoExecutionSite_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *EProtoExecutionSite) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(EProtoExecutionSite_value, data, "EProtoExecutionSite")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = EProtoExecutionSite(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (EProtoExecutionSite) EnumDescriptor() ([]byte, []int) { return base_fileDescriptor0, []int{0} }
|
|
||||||
|
|
||||||
type NoResponse struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *NoResponse) Reset() { *m = NoResponse{} }
|
|
||||||
func (m *NoResponse) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*NoResponse) ProtoMessage() {}
|
|
||||||
func (*NoResponse) Descriptor() ([]byte, []int) { return base_fileDescriptor0, []int{0} }
|
|
||||||
|
|
||||||
var E_Description = &proto.ExtensionDesc{
|
|
||||||
ExtendedType: (*google_protobuf.FieldOptions)(nil),
|
|
||||||
ExtensionType: (*string)(nil),
|
|
||||||
Field: 50000,
|
|
||||||
Name: "description",
|
|
||||||
Tag: "bytes,50000,opt,name=description",
|
|
||||||
}
|
|
||||||
|
|
||||||
var E_ServiceDescription = &proto.ExtensionDesc{
|
|
||||||
ExtendedType: (*google_protobuf.ServiceOptions)(nil),
|
|
||||||
ExtensionType: (*string)(nil),
|
|
||||||
Field: 50000,
|
|
||||||
Name: "service_description",
|
|
||||||
Tag: "bytes,50000,opt,name=service_description",
|
|
||||||
}
|
|
||||||
|
|
||||||
var E_ServiceExecutionSite = &proto.ExtensionDesc{
|
|
||||||
ExtendedType: (*google_protobuf.ServiceOptions)(nil),
|
|
||||||
ExtensionType: (*EProtoExecutionSite)(nil),
|
|
||||||
Field: 50008,
|
|
||||||
Name: "service_execution_site",
|
|
||||||
Tag: "varint,50008,opt,name=service_execution_site,enum=EProtoExecutionSite,def=0",
|
|
||||||
}
|
|
||||||
|
|
||||||
var E_MethodDescription = &proto.ExtensionDesc{
|
|
||||||
ExtendedType: (*google_protobuf.MethodOptions)(nil),
|
|
||||||
ExtensionType: (*string)(nil),
|
|
||||||
Field: 50000,
|
|
||||||
Name: "method_description",
|
|
||||||
Tag: "bytes,50000,opt,name=method_description",
|
|
||||||
}
|
|
||||||
|
|
||||||
var E_EnumDescription = &proto.ExtensionDesc{
|
|
||||||
ExtendedType: (*google_protobuf.EnumOptions)(nil),
|
|
||||||
ExtensionType: (*string)(nil),
|
|
||||||
Field: 50000,
|
|
||||||
Name: "enum_description",
|
|
||||||
Tag: "bytes,50000,opt,name=enum_description",
|
|
||||||
}
|
|
||||||
|
|
||||||
var E_EnumValueDescription = &proto.ExtensionDesc{
|
|
||||||
ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
|
|
||||||
ExtensionType: (*string)(nil),
|
|
||||||
Field: 50000,
|
|
||||||
Name: "enum_value_description",
|
|
||||||
Tag: "bytes,50000,opt,name=enum_value_description",
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterType((*NoResponse)(nil), "NoResponse")
|
|
||||||
proto.RegisterEnum("EProtoExecutionSite", EProtoExecutionSite_name, EProtoExecutionSite_value)
|
|
||||||
proto.RegisterExtension(E_Description)
|
|
||||||
proto.RegisterExtension(E_ServiceDescription)
|
|
||||||
proto.RegisterExtension(E_ServiceExecutionSite)
|
|
||||||
proto.RegisterExtension(E_MethodDescription)
|
|
||||||
proto.RegisterExtension(E_EnumDescription)
|
|
||||||
proto.RegisterExtension(E_EnumValueDescription)
|
|
||||||
}
|
|
||||||
|
|
||||||
var base_fileDescriptor0 = []byte{
|
|
||||||
// 306 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x90, 0x4d, 0x4b, 0xc3, 0x40,
|
|
||||||
0x10, 0x86, 0x1b, 0xc5, 0x83, 0xa3, 0x48, 0x48, 0xa5, 0x88, 0x54, 0x8d, 0xe2, 0x41, 0x44, 0xb6,
|
|
||||||
0x20, 0x1e, 0x24, 0x88, 0x07, 0x4b, 0xc4, 0x8b, 0x1f, 0x18, 0xf4, 0x26, 0x21, 0x4d, 0xa6, 0x71,
|
|
||||||
0x69, 0xb2, 0x1b, 0xb2, 0xbb, 0xd5, 0xa3, 0x27, 0x7f, 0x9f, 0x47, 0x7f, 0x8e, 0xcd, 0x86, 0x80,
|
|
||||||
0xf9, 0x40, 0x8f, 0xc9, 0xfb, 0x3e, 0xb3, 0xcf, 0x0c, 0x9c, 0x08, 0x89, 0x41, 0x9a, 0xa2, 0x10,
|
|
||||||
0x41, 0x8c, 0xc2, 0x57, 0x8c, 0x4e, 0x29, 0x46, 0xfe, 0x24, 0x10, 0x48, 0x74, 0x14, 0x26, 0x14,
|
|
||||||
0x99, 0x24, 0x59, 0xce, 0x25, 0xdf, 0xb6, 0x63, 0xce, 0xe3, 0x04, 0x47, 0xfa, 0x6b, 0xa2, 0xa6,
|
|
||||||
0xa3, 0x08, 0x45, 0x98, 0xd3, 0x4c, 0xf2, 0xbc, 0x6c, 0x1c, 0xac, 0x03, 0xdc, 0xf1, 0x47, 0x14,
|
|
||||||
0x19, 0x67, 0x02, 0x8f, 0x5f, 0xa0, 0xef, 0x3e, 0x14, 0xff, 0xdd, 0x77, 0x0c, 0x95, 0xa4, 0x9c,
|
|
||||||
0x79, 0x54, 0xa2, 0x65, 0xc3, 0x70, 0xe6, 0x77, 0x04, 0x4f, 0x6c, 0xc6, 0xf8, 0x1b, 0x33, 0x7b,
|
|
||||||
0xd6, 0x21, 0xd8, 0x9d, 0x0d, 0xaf, 0x50, 0x1a, 0x6b, 0x25, 0x73, 0xc9, 0x39, 0x83, 0xb5, 0x4a,
|
|
||||||
0x60, 0x91, 0x5b, 0x3b, 0xa4, 0xd4, 0x23, 0x95, 0x1e, 0xb9, 0xa6, 0x98, 0x44, 0xf7, 0x3a, 0x15,
|
|
||||||
0x5b, 0x5f, 0x9f, 0xcb, 0xb6, 0x71, 0xb4, 0xea, 0x5c, 0x42, 0x5f, 0x60, 0x3e, 0xa7, 0x21, 0xfa,
|
|
||||||
0xbf, 0xe9, 0xbd, 0x16, 0xed, 0x95, 0xad, 0x26, 0xaf, 0x60, 0x50, 0xf1, 0x58, 0xb9, 0xf9, 0xa2,
|
|
||||||
0xd8, 0xeb, 0xdf, 0x11, 0xdf, 0x7a, 0xc4, 0xc6, 0xe9, 0x26, 0xe9, 0xd8, 0xcd, 0xf9, 0xf3, 0x28,
|
|
||||||
0xce, 0x05, 0x58, 0x29, 0xca, 0x57, 0x1e, 0xd5, 0xac, 0x77, 0x5b, 0x4f, 0xde, 0xea, 0x52, 0x53,
|
|
||||||
0xfa, 0x1c, 0x4c, 0x64, 0x2a, 0xad, 0xb1, 0xc3, 0x16, 0xeb, 0x2e, 0x2a, 0x4d, 0x72, 0x0c, 0x03,
|
|
||||||
0x4d, 0xce, 0x83, 0x44, 0xd5, 0x2f, 0xb6, 0xdf, 0xc9, 0x3f, 0x17, 0xbd, 0xc6, 0x90, 0xab, 0x95,
|
|
||||||
0x1b, 0xe3, 0xc3, 0xe8, 0xfd, 0x04, 0x00, 0x00, 0xff, 0xff, 0x5c, 0xf6, 0x07, 0xbb, 0x6e, 0x02,
|
|
||||||
0x00, 0x00,
|
|
||||||
}
|
|
||||||
1424
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/cloud.pb.go
generated
vendored
1424
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/cloud.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
874
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/credentials.pb.go
generated
vendored
874
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/credentials.pb.go
generated
vendored
@@ -1,874 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go.
|
|
||||||
// source: steammessages_credentials.steamclient.proto
|
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
package unified
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import fmt "fmt"
|
|
||||||
import math "math"
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
type CCredentials_TestAvailablePassword_Request struct {
|
|
||||||
Password *string `protobuf:"bytes,1,opt,name=password" json:"password,omitempty"`
|
|
||||||
ShaDigestPassword []byte `protobuf:"bytes,2,opt,name=sha_digest_password" json:"sha_digest_password,omitempty"`
|
|
||||||
AccountName *string `protobuf:"bytes,3,opt,name=account_name" json:"account_name,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Request) Reset() {
|
|
||||||
*m = CCredentials_TestAvailablePassword_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_TestAvailablePassword_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_TestAvailablePassword_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Request) GetPassword() string {
|
|
||||||
if m != nil && m.Password != nil {
|
|
||||||
return *m.Password
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Request) GetShaDigestPassword() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.ShaDigestPassword
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Request) GetAccountName() string {
|
|
||||||
if m != nil && m.AccountName != nil {
|
|
||||||
return *m.AccountName
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_TestAvailablePassword_Response struct {
|
|
||||||
IsValid *bool `protobuf:"varint,3,opt,name=is_valid" json:"is_valid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Response) Reset() {
|
|
||||||
*m = CCredentials_TestAvailablePassword_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_TestAvailablePassword_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_TestAvailablePassword_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_TestAvailablePassword_Response) GetIsValid() bool {
|
|
||||||
if m != nil && m.IsValid != nil {
|
|
||||||
return *m.IsValid
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_GetSteamGuardDetails_Request struct {
|
|
||||||
IncludeNewAuthentications *bool `protobuf:"varint,1,opt,name=include_new_authentications,def=1" json:"include_new_authentications,omitempty"`
|
|
||||||
Webcookie *string `protobuf:"bytes,2,opt,name=webcookie" json:"webcookie,omitempty"`
|
|
||||||
TimestampMinimumWanted *uint32 `protobuf:"fixed32,3,opt,name=timestamp_minimum_wanted" json:"timestamp_minimum_wanted,omitempty"`
|
|
||||||
Ipaddress *int32 `protobuf:"varint,4,opt,name=ipaddress" json:"ipaddress,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Request) Reset() {
|
|
||||||
*m = CCredentials_GetSteamGuardDetails_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Default_CCredentials_GetSteamGuardDetails_Request_IncludeNewAuthentications bool = true
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Request) GetIncludeNewAuthentications() bool {
|
|
||||||
if m != nil && m.IncludeNewAuthentications != nil {
|
|
||||||
return *m.IncludeNewAuthentications
|
|
||||||
}
|
|
||||||
return Default_CCredentials_GetSteamGuardDetails_Request_IncludeNewAuthentications
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Request) GetWebcookie() string {
|
|
||||||
if m != nil && m.Webcookie != nil {
|
|
||||||
return *m.Webcookie
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Request) GetTimestampMinimumWanted() uint32 {
|
|
||||||
if m != nil && m.TimestampMinimumWanted != nil {
|
|
||||||
return *m.TimestampMinimumWanted
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Request) GetIpaddress() int32 {
|
|
||||||
if m != nil && m.Ipaddress != nil {
|
|
||||||
return *m.Ipaddress
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_GetSteamGuardDetails_Response struct {
|
|
||||||
IsSteamguardEnabled *bool `protobuf:"varint,1,opt,name=is_steamguard_enabled" json:"is_steamguard_enabled,omitempty"`
|
|
||||||
TimestampSteamguardEnabled *uint32 `protobuf:"fixed32,2,opt,name=timestamp_steamguard_enabled" json:"timestamp_steamguard_enabled,omitempty"`
|
|
||||||
DeprecatedNewauthentication []*CCredentials_GetSteamGuardDetails_Response_NewAuthentication `protobuf:"bytes,3,rep,name=deprecated_newauthentication" json:"deprecated_newauthentication,omitempty"`
|
|
||||||
DeprecatedMachineNameUserchosen *string `protobuf:"bytes,4,opt,name=deprecated_machine_name_userchosen" json:"deprecated_machine_name_userchosen,omitempty"`
|
|
||||||
DeprecatedTimestampMachineSteamguardEnabled *uint32 `protobuf:"fixed32,5,opt,name=deprecated_timestamp_machine_steamguard_enabled" json:"deprecated_timestamp_machine_steamguard_enabled,omitempty"`
|
|
||||||
DeprecatedAuthenticationExistsFromGeolocBeforeMintime *bool `protobuf:"varint,6,opt,name=deprecated_authentication_exists_from_geoloc_before_mintime" json:"deprecated_authentication_exists_from_geoloc_before_mintime,omitempty"`
|
|
||||||
DeprecatedMachineId *uint64 `protobuf:"varint,7,opt,name=deprecated_machine_id" json:"deprecated_machine_id,omitempty"`
|
|
||||||
SessionData []*CCredentials_GetSteamGuardDetails_Response_SessionData `protobuf:"bytes,8,rep,name=session_data" json:"session_data,omitempty"`
|
|
||||||
IsTwofactorEnabled *bool `protobuf:"varint,9,opt,name=is_twofactor_enabled" json:"is_twofactor_enabled,omitempty"`
|
|
||||||
TimestampTwofactorEnabled *uint32 `protobuf:"fixed32,10,opt,name=timestamp_twofactor_enabled" json:"timestamp_twofactor_enabled,omitempty"`
|
|
||||||
IsPhoneVerified *bool `protobuf:"varint,11,opt,name=is_phone_verified" json:"is_phone_verified,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) Reset() {
|
|
||||||
*m = CCredentials_GetSteamGuardDetails_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{3}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetIsSteamguardEnabled() bool {
|
|
||||||
if m != nil && m.IsSteamguardEnabled != nil {
|
|
||||||
return *m.IsSteamguardEnabled
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetTimestampSteamguardEnabled() uint32 {
|
|
||||||
if m != nil && m.TimestampSteamguardEnabled != nil {
|
|
||||||
return *m.TimestampSteamguardEnabled
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetDeprecatedNewauthentication() []*CCredentials_GetSteamGuardDetails_Response_NewAuthentication {
|
|
||||||
if m != nil {
|
|
||||||
return m.DeprecatedNewauthentication
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetDeprecatedMachineNameUserchosen() string {
|
|
||||||
if m != nil && m.DeprecatedMachineNameUserchosen != nil {
|
|
||||||
return *m.DeprecatedMachineNameUserchosen
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetDeprecatedTimestampMachineSteamguardEnabled() uint32 {
|
|
||||||
if m != nil && m.DeprecatedTimestampMachineSteamguardEnabled != nil {
|
|
||||||
return *m.DeprecatedTimestampMachineSteamguardEnabled
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetDeprecatedAuthenticationExistsFromGeolocBeforeMintime() bool {
|
|
||||||
if m != nil && m.DeprecatedAuthenticationExistsFromGeolocBeforeMintime != nil {
|
|
||||||
return *m.DeprecatedAuthenticationExistsFromGeolocBeforeMintime
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetDeprecatedMachineId() uint64 {
|
|
||||||
if m != nil && m.DeprecatedMachineId != nil {
|
|
||||||
return *m.DeprecatedMachineId
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetSessionData() []*CCredentials_GetSteamGuardDetails_Response_SessionData {
|
|
||||||
if m != nil {
|
|
||||||
return m.SessionData
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetIsTwofactorEnabled() bool {
|
|
||||||
if m != nil && m.IsTwofactorEnabled != nil {
|
|
||||||
return *m.IsTwofactorEnabled
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetTimestampTwofactorEnabled() uint32 {
|
|
||||||
if m != nil && m.TimestampTwofactorEnabled != nil {
|
|
||||||
return *m.TimestampTwofactorEnabled
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response) GetIsPhoneVerified() bool {
|
|
||||||
if m != nil && m.IsPhoneVerified != nil {
|
|
||||||
return *m.IsPhoneVerified
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_GetSteamGuardDetails_Response_NewAuthentication struct {
|
|
||||||
TimestampSteamguardEnabled *uint32 `protobuf:"fixed32,1,opt,name=timestamp_steamguard_enabled" json:"timestamp_steamguard_enabled,omitempty"`
|
|
||||||
IsWebCookie *bool `protobuf:"varint,2,opt,name=is_web_cookie" json:"is_web_cookie,omitempty"`
|
|
||||||
Ipaddress *int32 `protobuf:"varint,3,opt,name=ipaddress" json:"ipaddress,omitempty"`
|
|
||||||
GeolocInfo *string `protobuf:"bytes,4,opt,name=geoloc_info" json:"geoloc_info,omitempty"`
|
|
||||||
IsRemembered *bool `protobuf:"varint,5,opt,name=is_remembered" json:"is_remembered,omitempty"`
|
|
||||||
MachineNameUserSupplied *string `protobuf:"bytes,6,opt,name=machine_name_user_supplied" json:"machine_name_user_supplied,omitempty"`
|
|
||||||
Status *int32 `protobuf:"varint,7,opt,name=status" json:"status,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) Reset() {
|
|
||||||
*m = CCredentials_GetSteamGuardDetails_Response_NewAuthentication{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Response_NewAuthentication) ProtoMessage() {}
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Response_NewAuthentication) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{3, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) GetTimestampSteamguardEnabled() uint32 {
|
|
||||||
if m != nil && m.TimestampSteamguardEnabled != nil {
|
|
||||||
return *m.TimestampSteamguardEnabled
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) GetIsWebCookie() bool {
|
|
||||||
if m != nil && m.IsWebCookie != nil {
|
|
||||||
return *m.IsWebCookie
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) GetIpaddress() int32 {
|
|
||||||
if m != nil && m.Ipaddress != nil {
|
|
||||||
return *m.Ipaddress
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) GetGeolocInfo() string {
|
|
||||||
if m != nil && m.GeolocInfo != nil {
|
|
||||||
return *m.GeolocInfo
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) GetIsRemembered() bool {
|
|
||||||
if m != nil && m.IsRemembered != nil {
|
|
||||||
return *m.IsRemembered
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) GetMachineNameUserSupplied() string {
|
|
||||||
if m != nil && m.MachineNameUserSupplied != nil {
|
|
||||||
return *m.MachineNameUserSupplied
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_NewAuthentication) GetStatus() int32 {
|
|
||||||
if m != nil && m.Status != nil {
|
|
||||||
return *m.Status
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_GetSteamGuardDetails_Response_SessionData struct {
|
|
||||||
MachineId *uint64 `protobuf:"varint,1,opt,name=machine_id" json:"machine_id,omitempty"`
|
|
||||||
MachineNameUserchosen *string `protobuf:"bytes,2,opt,name=machine_name_userchosen" json:"machine_name_userchosen,omitempty"`
|
|
||||||
TimestampMachineSteamguardEnabled *uint32 `protobuf:"fixed32,3,opt,name=timestamp_machine_steamguard_enabled" json:"timestamp_machine_steamguard_enabled,omitempty"`
|
|
||||||
AuthenticationExistsFromGeolocBeforeMintime *bool `protobuf:"varint,4,opt,name=authentication_exists_from_geoloc_before_mintime" json:"authentication_exists_from_geoloc_before_mintime,omitempty"`
|
|
||||||
Newauthentication []*CCredentials_GetSteamGuardDetails_Response_NewAuthentication `protobuf:"bytes,5,rep,name=newauthentication" json:"newauthentication,omitempty"`
|
|
||||||
AuthenticationExistsFromSameIpBeforeMintime *bool `protobuf:"varint,6,opt,name=authentication_exists_from_same_ip_before_mintime" json:"authentication_exists_from_same_ip_before_mintime,omitempty"`
|
|
||||||
PublicIpv4 *uint32 `protobuf:"varint,7,opt,name=public_ipv4" json:"public_ipv4,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) Reset() {
|
|
||||||
*m = CCredentials_GetSteamGuardDetails_Response_SessionData{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Response_SessionData) ProtoMessage() {}
|
|
||||||
func (*CCredentials_GetSteamGuardDetails_Response_SessionData) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{3, 1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) GetMachineId() uint64 {
|
|
||||||
if m != nil && m.MachineId != nil {
|
|
||||||
return *m.MachineId
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) GetMachineNameUserchosen() string {
|
|
||||||
if m != nil && m.MachineNameUserchosen != nil {
|
|
||||||
return *m.MachineNameUserchosen
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) GetTimestampMachineSteamguardEnabled() uint32 {
|
|
||||||
if m != nil && m.TimestampMachineSteamguardEnabled != nil {
|
|
||||||
return *m.TimestampMachineSteamguardEnabled
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) GetAuthenticationExistsFromGeolocBeforeMintime() bool {
|
|
||||||
if m != nil && m.AuthenticationExistsFromGeolocBeforeMintime != nil {
|
|
||||||
return *m.AuthenticationExistsFromGeolocBeforeMintime
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) GetNewauthentication() []*CCredentials_GetSteamGuardDetails_Response_NewAuthentication {
|
|
||||||
if m != nil {
|
|
||||||
return m.Newauthentication
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) GetAuthenticationExistsFromSameIpBeforeMintime() bool {
|
|
||||||
if m != nil && m.AuthenticationExistsFromSameIpBeforeMintime != nil {
|
|
||||||
return *m.AuthenticationExistsFromSameIpBeforeMintime
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetSteamGuardDetails_Response_SessionData) GetPublicIpv4() uint32 {
|
|
||||||
if m != nil && m.PublicIpv4 != nil {
|
|
||||||
return *m.PublicIpv4
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_NewMachineNotificationDialog_Request struct {
|
|
||||||
IsApproved *bool `protobuf:"varint,1,opt,name=is_approved" json:"is_approved,omitempty"`
|
|
||||||
IsWizardComplete *bool `protobuf:"varint,2,opt,name=is_wizard_complete" json:"is_wizard_complete,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_NewMachineNotificationDialog_Request) Reset() {
|
|
||||||
*m = CCredentials_NewMachineNotificationDialog_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_NewMachineNotificationDialog_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_NewMachineNotificationDialog_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_NewMachineNotificationDialog_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{4}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_NewMachineNotificationDialog_Request) GetIsApproved() bool {
|
|
||||||
if m != nil && m.IsApproved != nil {
|
|
||||||
return *m.IsApproved
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_NewMachineNotificationDialog_Request) GetIsWizardComplete() bool {
|
|
||||||
if m != nil && m.IsWizardComplete != nil {
|
|
||||||
return *m.IsWizardComplete
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_NewMachineNotificationDialog_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_NewMachineNotificationDialog_Response) Reset() {
|
|
||||||
*m = CCredentials_NewMachineNotificationDialog_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_NewMachineNotificationDialog_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_NewMachineNotificationDialog_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_NewMachineNotificationDialog_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{5}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_ValidateEmailAddress_Request struct {
|
|
||||||
Stoken *string `protobuf:"bytes,1,opt,name=stoken" json:"stoken,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_ValidateEmailAddress_Request) Reset() {
|
|
||||||
*m = CCredentials_ValidateEmailAddress_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_ValidateEmailAddress_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CCredentials_ValidateEmailAddress_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_ValidateEmailAddress_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{6}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_ValidateEmailAddress_Request) GetStoken() string {
|
|
||||||
if m != nil && m.Stoken != nil {
|
|
||||||
return *m.Stoken
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_ValidateEmailAddress_Response struct {
|
|
||||||
WasValidated *bool `protobuf:"varint,1,opt,name=was_validated" json:"was_validated,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_ValidateEmailAddress_Response) Reset() {
|
|
||||||
*m = CCredentials_ValidateEmailAddress_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_ValidateEmailAddress_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_ValidateEmailAddress_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_ValidateEmailAddress_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{7}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_ValidateEmailAddress_Response) GetWasValidated() bool {
|
|
||||||
if m != nil && m.WasValidated != nil {
|
|
||||||
return *m.WasValidated
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_SteamGuardPhishingReport_Request struct {
|
|
||||||
ParamString *string `protobuf:"bytes,1,opt,name=param_string" json:"param_string,omitempty"`
|
|
||||||
IpaddressActual *uint32 `protobuf:"varint,2,opt,name=ipaddress_actual" json:"ipaddress_actual,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Request) Reset() {
|
|
||||||
*m = CCredentials_SteamGuardPhishingReport_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_SteamGuardPhishingReport_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_SteamGuardPhishingReport_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{8}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Request) GetParamString() string {
|
|
||||||
if m != nil && m.ParamString != nil {
|
|
||||||
return *m.ParamString
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Request) GetIpaddressActual() uint32 {
|
|
||||||
if m != nil && m.IpaddressActual != nil {
|
|
||||||
return *m.IpaddressActual
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_SteamGuardPhishingReport_Response struct {
|
|
||||||
IpaddressLoginattempt *uint32 `protobuf:"varint,1,opt,name=ipaddress_loginattempt" json:"ipaddress_loginattempt,omitempty"`
|
|
||||||
CountrynameLoginattempt *string `protobuf:"bytes,2,opt,name=countryname_loginattempt" json:"countryname_loginattempt,omitempty"`
|
|
||||||
StatenameLoginattempt *string `protobuf:"bytes,3,opt,name=statename_loginattempt" json:"statename_loginattempt,omitempty"`
|
|
||||||
CitynameLoginattempt *string `protobuf:"bytes,4,opt,name=cityname_loginattempt" json:"cityname_loginattempt,omitempty"`
|
|
||||||
IpaddressActual *uint32 `protobuf:"varint,5,opt,name=ipaddress_actual" json:"ipaddress_actual,omitempty"`
|
|
||||||
CountrynameActual *string `protobuf:"bytes,6,opt,name=countryname_actual" json:"countryname_actual,omitempty"`
|
|
||||||
StatenameActual *string `protobuf:"bytes,7,opt,name=statename_actual" json:"statename_actual,omitempty"`
|
|
||||||
CitynameActual *string `protobuf:"bytes,8,opt,name=cityname_actual" json:"cityname_actual,omitempty"`
|
|
||||||
SteamguardCode *string `protobuf:"bytes,9,opt,name=steamguard_code" json:"steamguard_code,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) Reset() {
|
|
||||||
*m = CCredentials_SteamGuardPhishingReport_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_SteamGuardPhishingReport_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_SteamGuardPhishingReport_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{9}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetIpaddressLoginattempt() uint32 {
|
|
||||||
if m != nil && m.IpaddressLoginattempt != nil {
|
|
||||||
return *m.IpaddressLoginattempt
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetCountrynameLoginattempt() string {
|
|
||||||
if m != nil && m.CountrynameLoginattempt != nil {
|
|
||||||
return *m.CountrynameLoginattempt
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetStatenameLoginattempt() string {
|
|
||||||
if m != nil && m.StatenameLoginattempt != nil {
|
|
||||||
return *m.StatenameLoginattempt
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetCitynameLoginattempt() string {
|
|
||||||
if m != nil && m.CitynameLoginattempt != nil {
|
|
||||||
return *m.CitynameLoginattempt
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetIpaddressActual() uint32 {
|
|
||||||
if m != nil && m.IpaddressActual != nil {
|
|
||||||
return *m.IpaddressActual
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetCountrynameActual() string {
|
|
||||||
if m != nil && m.CountrynameActual != nil {
|
|
||||||
return *m.CountrynameActual
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetStatenameActual() string {
|
|
||||||
if m != nil && m.StatenameActual != nil {
|
|
||||||
return *m.StatenameActual
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetCitynameActual() string {
|
|
||||||
if m != nil && m.CitynameActual != nil {
|
|
||||||
return *m.CitynameActual
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_SteamGuardPhishingReport_Response) GetSteamguardCode() string {
|
|
||||||
if m != nil && m.SteamguardCode != nil {
|
|
||||||
return *m.SteamguardCode
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_AccountLockRequest_Request struct {
|
|
||||||
ParamString *string `protobuf:"bytes,1,opt,name=param_string" json:"param_string,omitempty"`
|
|
||||||
IpaddressActual *uint32 `protobuf:"varint,2,opt,name=ipaddress_actual" json:"ipaddress_actual,omitempty"`
|
|
||||||
QueryOnly *bool `protobuf:"varint,3,opt,name=query_only" json:"query_only,omitempty"`
|
|
||||||
EmailMessageType *int32 `protobuf:"varint,4,opt,name=email_message_type" json:"email_message_type,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Request) Reset() {
|
|
||||||
*m = CCredentials_AccountLockRequest_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_AccountLockRequest_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CCredentials_AccountLockRequest_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_AccountLockRequest_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{10}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Request) GetParamString() string {
|
|
||||||
if m != nil && m.ParamString != nil {
|
|
||||||
return *m.ParamString
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Request) GetIpaddressActual() uint32 {
|
|
||||||
if m != nil && m.IpaddressActual != nil {
|
|
||||||
return *m.IpaddressActual
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Request) GetQueryOnly() bool {
|
|
||||||
if m != nil && m.QueryOnly != nil {
|
|
||||||
return *m.QueryOnly
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Request) GetEmailMessageType() int32 {
|
|
||||||
if m != nil && m.EmailMessageType != nil {
|
|
||||||
return *m.EmailMessageType
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_AccountLockRequest_Response struct {
|
|
||||||
Success *bool `protobuf:"varint,1,opt,name=success" json:"success,omitempty"`
|
|
||||||
AccountAlreadyLocked *bool `protobuf:"varint,2,opt,name=account_already_locked" json:"account_already_locked,omitempty"`
|
|
||||||
ExpiredLink *bool `protobuf:"varint,3,opt,name=expired_link" json:"expired_link,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Response) Reset() {
|
|
||||||
*m = CCredentials_AccountLockRequest_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_AccountLockRequest_Response) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CCredentials_AccountLockRequest_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_AccountLockRequest_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{11}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Response) GetSuccess() bool {
|
|
||||||
if m != nil && m.Success != nil {
|
|
||||||
return *m.Success
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Response) GetAccountAlreadyLocked() bool {
|
|
||||||
if m != nil && m.AccountAlreadyLocked != nil {
|
|
||||||
return *m.AccountAlreadyLocked
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_AccountLockRequest_Response) GetExpiredLink() bool {
|
|
||||||
if m != nil && m.ExpiredLink != nil {
|
|
||||||
return *m.ExpiredLink
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_LastCredentialChangeTime_Request struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_LastCredentialChangeTime_Request) Reset() {
|
|
||||||
*m = CCredentials_LastCredentialChangeTime_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_LastCredentialChangeTime_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_LastCredentialChangeTime_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_LastCredentialChangeTime_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{12}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_LastCredentialChangeTime_Response struct {
|
|
||||||
TimestampLastPasswordChange *uint32 `protobuf:"fixed32,1,opt,name=timestamp_last_password_change" json:"timestamp_last_password_change,omitempty"`
|
|
||||||
TimestampLastEmailChange *uint32 `protobuf:"fixed32,2,opt,name=timestamp_last_email_change" json:"timestamp_last_email_change,omitempty"`
|
|
||||||
TimestampLastPasswordReset *uint32 `protobuf:"fixed32,3,opt,name=timestamp_last_password_reset" json:"timestamp_last_password_reset,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_LastCredentialChangeTime_Response) Reset() {
|
|
||||||
*m = CCredentials_LastCredentialChangeTime_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_LastCredentialChangeTime_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_LastCredentialChangeTime_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_LastCredentialChangeTime_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{13}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_LastCredentialChangeTime_Response) GetTimestampLastPasswordChange() uint32 {
|
|
||||||
if m != nil && m.TimestampLastPasswordChange != nil {
|
|
||||||
return *m.TimestampLastPasswordChange
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_LastCredentialChangeTime_Response) GetTimestampLastEmailChange() uint32 {
|
|
||||||
if m != nil && m.TimestampLastEmailChange != nil {
|
|
||||||
return *m.TimestampLastEmailChange
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_LastCredentialChangeTime_Response) GetTimestampLastPasswordReset() uint32 {
|
|
||||||
if m != nil && m.TimestampLastPasswordReset != nil {
|
|
||||||
return *m.TimestampLastPasswordReset
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_GetAccountAuthSecret_Request struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetAccountAuthSecret_Request) Reset() {
|
|
||||||
*m = CCredentials_GetAccountAuthSecret_Request{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_GetAccountAuthSecret_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CCredentials_GetAccountAuthSecret_Request) ProtoMessage() {}
|
|
||||||
func (*CCredentials_GetAccountAuthSecret_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{14}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CCredentials_GetAccountAuthSecret_Response struct {
|
|
||||||
SecretId *int32 `protobuf:"varint,1,opt,name=secret_id" json:"secret_id,omitempty"`
|
|
||||||
Secret []byte `protobuf:"bytes,2,opt,name=secret" json:"secret,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetAccountAuthSecret_Response) Reset() {
|
|
||||||
*m = CCredentials_GetAccountAuthSecret_Response{}
|
|
||||||
}
|
|
||||||
func (m *CCredentials_GetAccountAuthSecret_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CCredentials_GetAccountAuthSecret_Response) ProtoMessage() {}
|
|
||||||
func (*CCredentials_GetAccountAuthSecret_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return credentials_fileDescriptor0, []int{15}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetAccountAuthSecret_Response) GetSecretId() int32 {
|
|
||||||
if m != nil && m.SecretId != nil {
|
|
||||||
return *m.SecretId
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CCredentials_GetAccountAuthSecret_Response) GetSecret() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Secret
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterType((*CCredentials_TestAvailablePassword_Request)(nil), "CCredentials_TestAvailablePassword_Request")
|
|
||||||
proto.RegisterType((*CCredentials_TestAvailablePassword_Response)(nil), "CCredentials_TestAvailablePassword_Response")
|
|
||||||
proto.RegisterType((*CCredentials_GetSteamGuardDetails_Request)(nil), "CCredentials_GetSteamGuardDetails_Request")
|
|
||||||
proto.RegisterType((*CCredentials_GetSteamGuardDetails_Response)(nil), "CCredentials_GetSteamGuardDetails_Response")
|
|
||||||
proto.RegisterType((*CCredentials_GetSteamGuardDetails_Response_NewAuthentication)(nil), "CCredentials_GetSteamGuardDetails_Response.NewAuthentication")
|
|
||||||
proto.RegisterType((*CCredentials_GetSteamGuardDetails_Response_SessionData)(nil), "CCredentials_GetSteamGuardDetails_Response.SessionData")
|
|
||||||
proto.RegisterType((*CCredentials_NewMachineNotificationDialog_Request)(nil), "CCredentials_NewMachineNotificationDialog_Request")
|
|
||||||
proto.RegisterType((*CCredentials_NewMachineNotificationDialog_Response)(nil), "CCredentials_NewMachineNotificationDialog_Response")
|
|
||||||
proto.RegisterType((*CCredentials_ValidateEmailAddress_Request)(nil), "CCredentials_ValidateEmailAddress_Request")
|
|
||||||
proto.RegisterType((*CCredentials_ValidateEmailAddress_Response)(nil), "CCredentials_ValidateEmailAddress_Response")
|
|
||||||
proto.RegisterType((*CCredentials_SteamGuardPhishingReport_Request)(nil), "CCredentials_SteamGuardPhishingReport_Request")
|
|
||||||
proto.RegisterType((*CCredentials_SteamGuardPhishingReport_Response)(nil), "CCredentials_SteamGuardPhishingReport_Response")
|
|
||||||
proto.RegisterType((*CCredentials_AccountLockRequest_Request)(nil), "CCredentials_AccountLockRequest_Request")
|
|
||||||
proto.RegisterType((*CCredentials_AccountLockRequest_Response)(nil), "CCredentials_AccountLockRequest_Response")
|
|
||||||
proto.RegisterType((*CCredentials_LastCredentialChangeTime_Request)(nil), "CCredentials_LastCredentialChangeTime_Request")
|
|
||||||
proto.RegisterType((*CCredentials_LastCredentialChangeTime_Response)(nil), "CCredentials_LastCredentialChangeTime_Response")
|
|
||||||
proto.RegisterType((*CCredentials_GetAccountAuthSecret_Request)(nil), "CCredentials_GetAccountAuthSecret_Request")
|
|
||||||
proto.RegisterType((*CCredentials_GetAccountAuthSecret_Response)(nil), "CCredentials_GetAccountAuthSecret_Response")
|
|
||||||
}
|
|
||||||
|
|
||||||
var credentials_fileDescriptor0 = []byte{
|
|
||||||
// 1482 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x5d, 0x6f, 0x14, 0xd5,
|
|
||||||
0x1b, 0xcf, 0x94, 0xbe, 0xec, 0x3e, 0xa5, 0x7f, 0xe8, 0x40, 0x61, 0x59, 0x0a, 0x4c, 0x06, 0xfe,
|
|
||||||
0xb6, 0xd0, 0x3a, 0x48, 0x25, 0x41, 0x25, 0xc6, 0x94, 0x56, 0x09, 0x06, 0x90, 0x00, 0x51, 0xef,
|
|
||||||
0x4e, 0x4e, 0x67, 0x4e, 0x77, 0x4f, 0x3a, 0x33, 0x67, 0x98, 0x39, 0xb3, 0x4b, 0x4d, 0x4c, 0xc4,
|
|
||||||
0x3b, 0xbc, 0xf0, 0xce, 0x0b, 0x13, 0x2f, 0x8d, 0x5f, 0xc0, 0xe8, 0x17, 0xf0, 0x2b, 0xf8, 0x25,
|
|
||||||
0xbc, 0x32, 0x7e, 0x03, 0x9f, 0x73, 0xe6, 0xec, 0xfb, 0x6c, 0xbb, 0x4b, 0xbc, 0xdc, 0x39, 0xcf,
|
|
||||||
0xcb, 0xef, 0xf9, 0x3d, 0xaf, 0x0b, 0x1b, 0x99, 0x64, 0x34, 0x8a, 0x58, 0x96, 0xd1, 0x06, 0xcb,
|
|
||||||
0x88, 0x9f, 0xb2, 0x80, 0xc5, 0x92, 0xd3, 0x30, 0xf3, 0xf4, 0x8b, 0x1f, 0x72, 0xfc, 0xed, 0x25,
|
|
||||||
0xa9, 0x90, 0xa2, 0xbe, 0x39, 0x28, 0x9c, 0xc7, 0x7c, 0x9f, 0xb3, 0x80, 0xec, 0xd1, 0x8c, 0x8d,
|
|
||||||
0x4a, 0xbb, 0x2f, 0xe0, 0xc6, 0xce, 0x4e, 0xcf, 0x1e, 0x79, 0xce, 0x32, 0xb9, 0xdd, 0xa2, 0x3c,
|
|
||||||
0xa4, 0x7b, 0x21, 0x7b, 0x42, 0xb3, 0xac, 0x2d, 0xd2, 0x80, 0x3c, 0x65, 0x2f, 0x72, 0x7c, 0xb0,
|
|
||||||
0x4f, 0x43, 0x25, 0x31, 0xdf, 0x6a, 0x96, 0x63, 0xad, 0x57, 0xed, 0x8b, 0x70, 0x26, 0x6b, 0x52,
|
|
||||||
0x12, 0x70, 0xf4, 0x25, 0x49, 0xf7, 0x71, 0x06, 0x1f, 0x4f, 0xda, 0x67, 0xe1, 0x24, 0xf5, 0x7d,
|
|
||||||
0x91, 0xc7, 0x92, 0xc4, 0x34, 0x62, 0xb5, 0x13, 0x4a, 0xc5, 0xfd, 0x08, 0x36, 0x26, 0x72, 0x99,
|
|
||||||
0x25, 0x22, 0xce, 0x98, 0xf2, 0xc9, 0x33, 0xd2, 0xa2, 0x21, 0x0f, 0xb4, 0x81, 0x8a, 0xfb, 0xf7,
|
|
||||||
0x0c, 0x5c, 0x1f, 0xb0, 0x70, 0x9f, 0xc9, 0x67, 0x2a, 0xb2, 0xfb, 0x39, 0x4d, 0x83, 0x5d, 0x26,
|
|
||||||
0xd1, 0x56, 0xd6, 0xc5, 0x9c, 0xc3, 0x45, 0x1e, 0xfb, 0x61, 0x1e, 0x30, 0x12, 0xb3, 0x36, 0xa1,
|
|
||||||
0xb9, 0x6c, 0x2a, 0x3d, 0x9f, 0x4a, 0x8e, 0xf6, 0x75, 0x18, 0x95, 0x0f, 0x66, 0x65, 0x9a, 0xb3,
|
|
||||||
0x7b, 0x9f, 0x7e, 0xfb, 0x5b, 0xed, 0x93, 0x2f, 0x9a, 0x0c, 0x25, 0x52, 0x47, 0xa4, 0x4e, 0x2c,
|
|
||||||
0xa4, 0x23, 0x85, 0x93, 0x88, 0x24, 0x0f, 0xa9, 0x64, 0x0e, 0x7e, 0x77, 0xd0, 0xc6, 0xa0, 0x09,
|
|
||||||
0x07, 0xe9, 0x0d, 0x03, 0x87, 0xc7, 0xfa, 0x39, 0xed, 0xc0, 0xfe, 0xc1, 0x82, 0x6a, 0x9b, 0xed,
|
|
||||||
0xf9, 0x42, 0x1c, 0x70, 0xa6, 0xf9, 0xa8, 0xde, 0x7b, 0x65, 0xa1, 0x83, 0xaf, 0x9f, 0xa3, 0x58,
|
|
||||||
0x9e, 0xb1, 0x74, 0x2d, 0x73, 0x34, 0x6a, 0x47, 0xc3, 0x76, 0x22, 0xea, 0x37, 0x79, 0xcc, 0x1c,
|
|
||||||
0x65, 0xdd, 0x29, 0xd4, 0x3c, 0xe7, 0xc1, 0xbe, 0x93, 0xa0, 0x49, 0xf4, 0xb6, 0xe9, 0x70, 0xb9,
|
|
||||||
0x16, 0x86, 0xce, 0x9e, 0x56, 0x0e, 0x14, 0xae, 0x06, 0x93, 0xda, 0xa7, 0x31, 0xd6, 0x31, 0xf0,
|
|
||||||
0x60, 0x17, 0xc1, 0xa8, 0x4c, 0x07, 0x8e, 0xd8, 0xd7, 0x02, 0xdb, 0x8f, 0x9c, 0x0c, 0xeb, 0x01,
|
|
||||||
0xc1, 0x7a, 0xb6, 0x03, 0x35, 0xc9, 0xb1, 0x3a, 0x24, 0x8d, 0x12, 0x12, 0xf1, 0x98, 0x47, 0x79,
|
|
||||||
0x44, 0xda, 0x34, 0x96, 0xac, 0xa0, 0x77, 0xc1, 0x5e, 0x86, 0x2a, 0x4f, 0x68, 0x10, 0xa0, 0xdf,
|
|
||||||
0xac, 0x36, 0x8b, 0x9f, 0xe6, 0xdc, 0xbf, 0x2a, 0x43, 0x65, 0x32, 0x86, 0x71, 0x13, 0xfb, 0x25,
|
|
||||||
0x58, 0xc1, 0x94, 0xe9, 0x62, 0x6b, 0x28, 0x01, 0xc2, 0x62, 0x95, 0xdb, 0xa2, 0x66, 0x2a, 0xf6,
|
|
||||||
0x35, 0x58, 0xed, 0x41, 0x28, 0x91, 0x9a, 0xd1, 0x30, 0x7c, 0x58, 0x0d, 0x18, 0x06, 0x8f, 0x2c,
|
|
||||||
0x63, 0xf9, 0x8e, 0xd0, 0x8e, 0x60, 0x4f, 0xac, 0x2f, 0x6e, 0x7d, 0xe8, 0x4d, 0x8e, 0xcb, 0x7b,
|
|
||||||
0xcc, 0xda, 0xdb, 0x03, 0x46, 0xec, 0x1b, 0xe0, 0xf6, 0x39, 0x31, 0x0c, 0xea, 0x62, 0x25, 0x8a,
|
|
||||||
0x55, 0xbf, 0x29, 0x90, 0x7b, 0x4d, 0x42, 0xd5, 0xbe, 0x03, 0x37, 0xfb, 0x64, 0xfb, 0x48, 0x34,
|
|
||||||
0x5a, 0x25, 0x91, 0xcc, 0xe9, 0x48, 0x76, 0xe0, 0x6e, 0x9f, 0xe2, 0x60, 0x18, 0x84, 0xbd, 0xe4,
|
|
||||||
0x99, 0xcc, 0xc8, 0x7e, 0x2a, 0x22, 0xd2, 0x60, 0x22, 0x14, 0x3e, 0xd9, 0x63, 0xfb, 0x22, 0x65,
|
|
||||||
0x2a, 0x39, 0xca, 0x49, 0x6d, 0x5e, 0x93, 0x86, 0x9c, 0x96, 0x20, 0xc5, 0x9e, 0x58, 0xc0, 0xe7,
|
|
||||||
0x59, 0xfb, 0x11, 0x9c, 0x34, 0x29, 0x26, 0x01, 0x95, 0xb4, 0x56, 0xd1, 0xec, 0xdc, 0x99, 0x86,
|
|
||||||
0x9d, 0x67, 0x85, 0xfe, 0x2e, 0xaa, 0xdb, 0xab, 0x70, 0x16, 0x33, 0x28, 0xdb, 0x62, 0x9f, 0xfa,
|
|
||||||
0x52, 0xa4, 0xdd, 0x80, 0xaa, 0x1a, 0xcb, 0x55, 0xb8, 0xd8, 0x0b, 0x7f, 0x54, 0x08, 0x74, 0xd4,
|
|
||||||
0x17, 0x60, 0x19, 0x4d, 0x24, 0x4d, 0x81, 0x30, 0x5b, 0x2c, 0xd5, 0x53, 0xa8, 0xb6, 0xa8, 0xf4,
|
|
||||||
0xeb, 0x7f, 0x58, 0xb0, 0x3c, 0x9a, 0x8b, 0xe3, 0xca, 0xc2, 0xd2, 0x66, 0x57, 0x60, 0x09, 0xcd,
|
|
||||||
0x62, 0x67, 0x91, 0xbe, 0xd6, 0xaa, 0x0c, 0x16, 0xad, 0xaa, 0xe3, 0x39, 0xfb, 0x0c, 0x2c, 0x1a,
|
|
||||||
0x42, 0x79, 0xbc, 0x2f, 0x4c, 0x12, 0x0b, 0xf5, 0x94, 0x45, 0x2c, 0xda, 0x63, 0xa9, 0x49, 0x51,
|
|
||||||
0xc5, 0x76, 0xa1, 0x3e, 0x92, 0x7c, 0x92, 0xe5, 0x49, 0x12, 0x2a, 0xd4, 0xf3, 0x5a, 0xf5, 0x7f,
|
|
||||||
0x30, 0x8f, 0xd8, 0x64, 0x9e, 0x69, 0xca, 0xe7, 0xea, 0x7f, 0xce, 0xc0, 0x62, 0x3f, 0x67, 0x36,
|
|
||||||
0x40, 0x5f, 0x5a, 0x2c, 0x9d, 0x96, 0x2b, 0x70, 0x7e, 0x5c, 0x51, 0xe9, 0x91, 0x60, 0x6f, 0xc2,
|
|
||||||
0xb5, 0x89, 0x2a, 0xa9, 0x68, 0xcd, 0xf7, 0xe0, 0x9d, 0xa9, 0xcb, 0x67, 0x56, 0x07, 0xf8, 0x25,
|
|
||||||
0x2c, 0x8f, 0xb6, 0xd0, 0xdc, 0x7f, 0xd1, 0x42, 0xef, 0xc3, 0xad, 0x23, 0x30, 0x65, 0x2a, 0x6a,
|
|
||||||
0x9e, 0x94, 0xd7, 0x34, 0x66, 0x28, 0xc9, 0xf7, 0x42, 0x8e, 0x19, 0x4a, 0x5a, 0xb7, 0x35, 0xad,
|
|
||||||
0x4b, 0x6e, 0x00, 0xb7, 0x06, 0xf0, 0xa0, 0xc7, 0x47, 0x05, 0x2f, 0x8f, 0x85, 0xc4, 0x2a, 0x2a,
|
|
||||||
0x9c, 0xec, 0xe2, 0x9b, 0x68, 0x74, 0x87, 0x3c, 0x5a, 0xc2, 0xb4, 0xd2, 0x04, 0x97, 0x5a, 0xab,
|
|
||||||
0x3b, 0x67, 0xea, 0x60, 0xab, 0x52, 0xe1, 0x5f, 0x29, 0x22, 0x7d, 0x11, 0x25, 0x21, 0x93, 0xa6,
|
|
||||||
0x5e, 0xdc, 0xdb, 0xb0, 0x35, 0x8d, 0x97, 0x22, 0x7a, 0xf7, 0xee, 0xd0, 0xe2, 0xf9, 0x5c, 0x6d,
|
|
||||||
0x25, 0x6c, 0xc8, 0x8f, 0x23, 0x64, 0x69, 0xbb, 0xa8, 0xbe, 0x2e, 0x26, 0x5d, 0x2f, 0xe2, 0x00,
|
|
||||||
0x53, 0xad, 0x57, 0xa5, 0xbb, 0x33, 0x34, 0x43, 0xc7, 0x28, 0x9b, 0x19, 0x8a, 0x85, 0xda, 0xa6,
|
|
||||||
0x66, 0xef, 0xa9, 0x96, 0x2f, 0x62, 0x72, 0x09, 0xbc, 0x3d, 0x60, 0xa4, 0x97, 0xaa, 0x27, 0x4d,
|
|
||||||
0x9e, 0x21, 0xfe, 0xc6, 0x53, 0x96, 0x88, 0x54, 0x76, 0x51, 0xe0, 0x0e, 0x4e, 0x68, 0x4a, 0x31,
|
|
||||||
0x13, 0x32, 0xc5, 0x57, 0xb3, 0xb6, 0x6b, 0x70, 0xba, 0xdb, 0x2e, 0x04, 0xbb, 0x37, 0xa7, 0xa1,
|
|
||||||
0x26, 0x66, 0xc9, 0xfd, 0x75, 0x06, 0xbc, 0x49, 0x3d, 0x18, 0xa8, 0x97, 0xe1, 0x5c, 0xcf, 0x18,
|
|
||||||
0xf2, 0xc5, 0x63, 0x2a, 0x25, 0x8b, 0x12, 0xa9, 0x9d, 0x2d, 0xa9, 0x95, 0xa3, 0x8f, 0x80, 0xf4,
|
|
||||||
0x50, 0xf7, 0xc0, 0x80, 0x44, 0xd1, 0x05, 0x68, 0x41, 0xb5, 0x16, 0x1b, 0x7d, 0xd7, 0x27, 0x83,
|
|
||||||
0x1a, 0x7e, 0x3e, 0x97, 0x25, 0xea, 0xb3, 0x63, 0xa3, 0x99, 0xd3, 0xae, 0xb1, 0x04, 0xfa, 0x5d,
|
|
||||||
0x9b, 0xb7, 0xf9, 0x8e, 0x56, 0xcf, 0xa9, 0x79, 0x59, 0xd0, 0x2f, 0xe7, 0xe1, 0x54, 0xd7, 0x9d,
|
|
||||||
0x79, 0xa8, 0x74, 0x1e, 0xfa, 0x7a, 0xd3, 0x17, 0x01, 0xd3, 0x13, 0xb1, 0xea, 0xbe, 0xb6, 0x60,
|
|
||||||
0x6d, 0x80, 0xb5, 0xed, 0xe2, 0xee, 0x79, 0x28, 0xfc, 0x03, 0x93, 0x89, 0x37, 0xcd, 0x88, 0x9a,
|
|
||||||
0x2b, 0xa8, 0x98, 0x1e, 0x12, 0x11, 0x87, 0x87, 0xc5, 0x09, 0xa4, 0xe2, 0x62, 0xaa, 0x6c, 0x88,
|
|
||||||
0xb9, 0xf3, 0x88, 0x3c, 0x4c, 0x98, 0x59, 0xd6, 0x2f, 0x60, 0xfd, 0x78, 0x28, 0x26, 0x75, 0xa7,
|
|
||||||
0x60, 0x21, 0xcb, 0x7d, 0x5f, 0x0d, 0xcd, 0xa2, 0x67, 0x30, 0x13, 0x9d, 0x93, 0x8d, 0x86, 0x29,
|
|
||||||
0xde, 0x10, 0x87, 0x48, 0xb8, 0x7f, 0x60, 0xb6, 0x72, 0x45, 0x81, 0x67, 0x2f, 0x13, 0x8e, 0xe6,
|
|
||||||
0x49, 0xc8, 0xe3, 0x03, 0x73, 0x91, 0xdd, 0x1c, 0xaa, 0xca, 0x87, 0x34, 0x93, 0xbd, 0xdf, 0x3b,
|
|
||||||
0x4d, 0x1a, 0x37, 0xd8, 0x73, 0xec, 0xfb, 0x0e, 0x07, 0xee, 0xcf, 0xd6, 0x50, 0x95, 0x1d, 0xa1,
|
|
||||||
0x61, 0xa0, 0xbe, 0x05, 0x97, 0x7b, 0x93, 0x32, 0xa4, 0x7d, 0xd7, 0x26, 0xf1, 0xb5, 0xb8, 0x59,
|
|
||||||
0x10, 0x03, 0xcb, 0x49, 0xcb, 0x15, 0x4c, 0x19, 0xa1, 0xe2, 0xb8, 0xf8, 0x3f, 0x5c, 0x1a, 0x67,
|
|
||||||
0x4c, 0x9d, 0x5b, 0x45, 0xdd, 0x2d, 0xb8, 0x1b, 0xa3, 0x87, 0xa6, 0x61, 0x53, 0x0d, 0xc1, 0x67,
|
|
||||||
0x0c, 0x2f, 0xf1, 0x6e, 0x5e, 0xdd, 0xcf, 0x46, 0x6f, 0xa4, 0x32, 0x61, 0x13, 0x0e, 0x2e, 0xac,
|
|
||||||
0xac, 0xf8, 0x64, 0x96, 0xc5, 0x9c, 0x1e, 0x18, 0xfa, 0x53, 0x71, 0x3e, 0x6f, 0xfd, 0x53, 0x85,
|
|
||||||
0xc5, 0x3e, 0x83, 0xf6, 0xf7, 0x16, 0xac, 0x94, 0x1e, 0xcb, 0xf6, 0x86, 0x37, 0xf9, 0x11, 0x5f,
|
|
||||||
0xdf, 0xf4, 0xa6, 0x38, 0xbf, 0xdd, 0x3a, 0x9e, 0xac, 0xe7, 0x4a, 0x65, 0x3c, 0xfb, 0x3b, 0x0b,
|
|
||||||
0xce, 0x96, 0xad, 0x0b, 0xfb, 0x86, 0x37, 0xf1, 0x7d, 0x5e, 0xdf, 0x98, 0x62, 0xfd, 0xb8, 0x17,
|
|
||||||
0x10, 0xcd, 0x4a, 0x99, 0x88, 0x67, 0xff, 0x6e, 0x81, 0x7b, 0xd4, 0x14, 0x47, 0x1b, 0x79, 0x28,
|
|
||||||
0xed, 0x2d, 0x6f, 0xea, 0xed, 0x52, 0x7f, 0xd7, 0x7b, 0x83, 0x5d, 0xb1, 0x86, 0x50, 0xaf, 0x1e,
|
|
||||||
0x0f, 0xc8, 0xb3, 0x7f, 0x42, 0x16, 0xcb, 0x76, 0xc1, 0x30, 0x8b, 0x47, 0x2d, 0x9b, 0x61, 0x16,
|
|
||||||
0x8f, 0xdc, 0x2d, 0xee, 0x06, 0x42, 0x5b, 0xeb, 0x88, 0x38, 0x34, 0x76, 0x74, 0x87, 0x38, 0x66,
|
|
||||||
0xfa, 0x38, 0x0d, 0xde, 0x62, 0xb1, 0x43, 0x1d, 0xbd, 0xbc, 0xec, 0x1f, 0x2d, 0xa8, 0x8d, 0xdb,
|
|
||||||
0x01, 0xb6, 0xe7, 0x4d, 0xb5, 0x8d, 0xea, 0x37, 0xa7, 0xdc, 0x2d, 0xee, 0x2a, 0x42, 0x1d, 0xef,
|
|
||||||
0xfe, 0x95, 0x05, 0xf6, 0xe8, 0x78, 0xb3, 0xd7, 0xbd, 0x09, 0x67, 0x71, 0xfd, 0xba, 0x37, 0xe9,
|
|
||||||
0xa8, 0x74, 0xcf, 0x21, 0x92, 0x32, 0x67, 0xbf, 0x58, 0x70, 0x19, 0x2b, 0xb2, 0x6c, 0x78, 0x75,
|
|
||||||
0xda, 0xc1, 0xf3, 0xa6, 0x9a, 0x8e, 0xc3, 0x2c, 0x1d, 0x3b, 0x1b, 0xdd, 0xab, 0x88, 0xed, 0xca,
|
|
||||||
0xd1, 0x20, 0x3c, 0xfb, 0x75, 0xd1, 0xad, 0x23, 0x33, 0xa9, 0xa4, 0x5b, 0xc7, 0x0e, 0xb9, 0x92,
|
|
||||||
0x6e, 0x1d, 0x3f, 0xe3, 0xdc, 0x1a, 0xc2, 0x2a, 0x75, 0x59, 0x3f, 0x8f, 0x2f, 0x67, 0xfa, 0x0c,
|
|
||||||
0xe1, 0xff, 0xd3, 0xb4, 0xc5, 0x7d, 0x76, 0xef, 0xc4, 0x37, 0x96, 0xf5, 0x6f, 0x00, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0x3c, 0x6e, 0x05, 0xde, 0xf0, 0x10, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
694
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/deviceauth.pb.go
generated
vendored
694
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/deviceauth.pb.go
generated
vendored
@@ -1,694 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go.
|
|
||||||
// source: steammessages_deviceauth.steamclient.proto
|
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
package unified
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import fmt "fmt"
|
|
||||||
import math "math"
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
type CDeviceAuth_GetOwnAuthorizedDevices_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
IncludeCanceled *bool `protobuf:"varint,2,opt,name=include_canceled" json:"include_canceled,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_GetOwnAuthorizedDevices_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetOwnAuthorizedDevices_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetOwnAuthorizedDevices_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Request) GetIncludeCanceled() bool {
|
|
||||||
if m != nil && m.IncludeCanceled != nil {
|
|
||||||
return *m.IncludeCanceled
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetOwnAuthorizedDevices_Response struct {
|
|
||||||
Devices []*CDeviceAuth_GetOwnAuthorizedDevices_Response_Device `protobuf:"bytes,1,rep,name=devices" json:"devices,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_GetOwnAuthorizedDevices_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetOwnAuthorizedDevices_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetOwnAuthorizedDevices_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response) GetDevices() []*CDeviceAuth_GetOwnAuthorizedDevices_Response_Device {
|
|
||||||
if m != nil {
|
|
||||||
return m.Devices
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetOwnAuthorizedDevices_Response_Device struct {
|
|
||||||
AuthDeviceToken *uint64 `protobuf:"fixed64,1,opt,name=auth_device_token" json:"auth_device_token,omitempty"`
|
|
||||||
DeviceName *string `protobuf:"bytes,2,opt,name=device_name" json:"device_name,omitempty"`
|
|
||||||
IsPending *bool `protobuf:"varint,3,opt,name=is_pending" json:"is_pending,omitempty"`
|
|
||||||
IsCanceled *bool `protobuf:"varint,4,opt,name=is_canceled" json:"is_canceled,omitempty"`
|
|
||||||
LastTimeUsed *uint32 `protobuf:"varint,5,opt,name=last_time_used" json:"last_time_used,omitempty"`
|
|
||||||
LastBorrowerId *uint64 `protobuf:"fixed64,6,opt,name=last_borrower_id" json:"last_borrower_id,omitempty"`
|
|
||||||
LastAppPlayed *uint32 `protobuf:"varint,7,opt,name=last_app_played" json:"last_app_played,omitempty"`
|
|
||||||
IsLimited *bool `protobuf:"varint,8,opt,name=is_limited" json:"is_limited,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) Reset() {
|
|
||||||
*m = CDeviceAuth_GetOwnAuthorizedDevices_Response_Device{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{1, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetAuthDeviceToken() uint64 {
|
|
||||||
if m != nil && m.AuthDeviceToken != nil {
|
|
||||||
return *m.AuthDeviceToken
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetDeviceName() string {
|
|
||||||
if m != nil && m.DeviceName != nil {
|
|
||||||
return *m.DeviceName
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetIsPending() bool {
|
|
||||||
if m != nil && m.IsPending != nil {
|
|
||||||
return *m.IsPending
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetIsCanceled() bool {
|
|
||||||
if m != nil && m.IsCanceled != nil {
|
|
||||||
return *m.IsCanceled
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetLastTimeUsed() uint32 {
|
|
||||||
if m != nil && m.LastTimeUsed != nil {
|
|
||||||
return *m.LastTimeUsed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetLastBorrowerId() uint64 {
|
|
||||||
if m != nil && m.LastBorrowerId != nil {
|
|
||||||
return *m.LastBorrowerId
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetLastAppPlayed() uint32 {
|
|
||||||
if m != nil && m.LastAppPlayed != nil {
|
|
||||||
return *m.LastAppPlayed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetOwnAuthorizedDevices_Response_Device) GetIsLimited() bool {
|
|
||||||
if m != nil && m.IsLimited != nil {
|
|
||||||
return *m.IsLimited
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_AcceptAuthorizationRequest_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
AuthDeviceToken *uint64 `protobuf:"fixed64,2,opt,name=auth_device_token" json:"auth_device_token,omitempty"`
|
|
||||||
AuthCode *uint64 `protobuf:"fixed64,3,opt,name=auth_code" json:"auth_code,omitempty"`
|
|
||||||
FromSteamid *uint64 `protobuf:"fixed64,4,opt,name=from_steamid" json:"from_steamid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_AcceptAuthorizationRequest_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_AcceptAuthorizationRequest_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_AcceptAuthorizationRequest_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Request) GetAuthDeviceToken() uint64 {
|
|
||||||
if m != nil && m.AuthDeviceToken != nil {
|
|
||||||
return *m.AuthDeviceToken
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Request) GetAuthCode() uint64 {
|
|
||||||
if m != nil && m.AuthCode != nil {
|
|
||||||
return *m.AuthCode
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Request) GetFromSteamid() uint64 {
|
|
||||||
if m != nil && m.FromSteamid != nil {
|
|
||||||
return *m.FromSteamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_AcceptAuthorizationRequest_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_AcceptAuthorizationRequest_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_AcceptAuthorizationRequest_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_AcceptAuthorizationRequest_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_AcceptAuthorizationRequest_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{3}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_AuthorizeRemoteDevice_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
AuthDeviceToken *uint64 `protobuf:"fixed64,2,opt,name=auth_device_token" json:"auth_device_token,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AuthorizeRemoteDevice_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_AuthorizeRemoteDevice_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_AuthorizeRemoteDevice_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CDeviceAuth_AuthorizeRemoteDevice_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_AuthorizeRemoteDevice_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{4}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AuthorizeRemoteDevice_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AuthorizeRemoteDevice_Request) GetAuthDeviceToken() uint64 {
|
|
||||||
if m != nil && m.AuthDeviceToken != nil {
|
|
||||||
return *m.AuthDeviceToken
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_AuthorizeRemoteDevice_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AuthorizeRemoteDevice_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_AuthorizeRemoteDevice_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_AuthorizeRemoteDevice_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_AuthorizeRemoteDevice_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_AuthorizeRemoteDevice_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{5}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_DeauthorizeRemoteDevice_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
AuthDeviceToken *uint64 `protobuf:"fixed64,2,opt,name=auth_device_token" json:"auth_device_token,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_DeauthorizeRemoteDevice_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_DeauthorizeRemoteDevice_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_DeauthorizeRemoteDevice_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_DeauthorizeRemoteDevice_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_DeauthorizeRemoteDevice_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{6}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_DeauthorizeRemoteDevice_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_DeauthorizeRemoteDevice_Request) GetAuthDeviceToken() uint64 {
|
|
||||||
if m != nil && m.AuthDeviceToken != nil {
|
|
||||||
return *m.AuthDeviceToken
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_DeauthorizeRemoteDevice_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_DeauthorizeRemoteDevice_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_DeauthorizeRemoteDevice_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_DeauthorizeRemoteDevice_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_DeauthorizeRemoteDevice_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_DeauthorizeRemoteDevice_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{7}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetUsedAuthorizedDevices_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_GetUsedAuthorizedDevices_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetUsedAuthorizedDevices_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetUsedAuthorizedDevices_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{8}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetUsedAuthorizedDevices_Response struct {
|
|
||||||
Devices []*CDeviceAuth_GetUsedAuthorizedDevices_Response_Device `protobuf:"bytes,1,rep,name=devices" json:"devices,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_GetUsedAuthorizedDevices_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetUsedAuthorizedDevices_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetUsedAuthorizedDevices_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{9}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response) GetDevices() []*CDeviceAuth_GetUsedAuthorizedDevices_Response_Device {
|
|
||||||
if m != nil {
|
|
||||||
return m.Devices
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetUsedAuthorizedDevices_Response_Device struct {
|
|
||||||
AuthDeviceToken *uint64 `protobuf:"fixed64,1,opt,name=auth_device_token" json:"auth_device_token,omitempty"`
|
|
||||||
DeviceName *string `protobuf:"bytes,2,opt,name=device_name" json:"device_name,omitempty"`
|
|
||||||
OwnerSteamid *uint64 `protobuf:"fixed64,3,opt,name=owner_steamid" json:"owner_steamid,omitempty"`
|
|
||||||
LastTimeUsed *uint32 `protobuf:"varint,4,opt,name=last_time_used" json:"last_time_used,omitempty"`
|
|
||||||
LastAppPlayed *uint32 `protobuf:"varint,5,opt,name=last_app_played" json:"last_app_played,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) Reset() {
|
|
||||||
*m = CDeviceAuth_GetUsedAuthorizedDevices_Response_Device{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{9, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) GetAuthDeviceToken() uint64 {
|
|
||||||
if m != nil && m.AuthDeviceToken != nil {
|
|
||||||
return *m.AuthDeviceToken
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) GetDeviceName() string {
|
|
||||||
if m != nil && m.DeviceName != nil {
|
|
||||||
return *m.DeviceName
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) GetOwnerSteamid() uint64 {
|
|
||||||
if m != nil && m.OwnerSteamid != nil {
|
|
||||||
return *m.OwnerSteamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) GetLastTimeUsed() uint32 {
|
|
||||||
if m != nil && m.LastTimeUsed != nil {
|
|
||||||
return *m.LastTimeUsed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetUsedAuthorizedDevices_Response_Device) GetLastAppPlayed() uint32 {
|
|
||||||
if m != nil && m.LastAppPlayed != nil {
|
|
||||||
return *m.LastAppPlayed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetAuthorizedBorrowers_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
IncludeCanceled *bool `protobuf:"varint,2,opt,name=include_canceled" json:"include_canceled,omitempty"`
|
|
||||||
IncludePending *bool `protobuf:"varint,3,opt,name=include_pending" json:"include_pending,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_GetAuthorizedBorrowers_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetAuthorizedBorrowers_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetAuthorizedBorrowers_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{10}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Request) GetIncludeCanceled() bool {
|
|
||||||
if m != nil && m.IncludeCanceled != nil {
|
|
||||||
return *m.IncludeCanceled
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Request) GetIncludePending() bool {
|
|
||||||
if m != nil && m.IncludePending != nil {
|
|
||||||
return *m.IncludePending
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetAuthorizedBorrowers_Response struct {
|
|
||||||
Borrowers []*CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower `protobuf:"bytes,1,rep,name=borrowers" json:"borrowers,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_GetAuthorizedBorrowers_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetAuthorizedBorrowers_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetAuthorizedBorrowers_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{11}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response) GetBorrowers() []*CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower {
|
|
||||||
if m != nil {
|
|
||||||
return m.Borrowers
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
IsPending *bool `protobuf:"varint,2,opt,name=is_pending" json:"is_pending,omitempty"`
|
|
||||||
IsCanceled *bool `protobuf:"varint,3,opt,name=is_canceled" json:"is_canceled,omitempty"`
|
|
||||||
TimeCreated *uint32 `protobuf:"varint,4,opt,name=time_created" json:"time_created,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) Reset() {
|
|
||||||
*m = CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{11, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) GetIsPending() bool {
|
|
||||||
if m != nil && m.IsPending != nil {
|
|
||||||
return *m.IsPending
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) GetIsCanceled() bool {
|
|
||||||
if m != nil && m.IsCanceled != nil {
|
|
||||||
return *m.IsCanceled
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower) GetTimeCreated() uint32 {
|
|
||||||
if m != nil && m.TimeCreated != nil {
|
|
||||||
return *m.TimeCreated
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_AddAuthorizedBorrowers_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
SteamidBorrower []uint64 `protobuf:"fixed64,2,rep,name=steamid_borrower" json:"steamid_borrower,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AddAuthorizedBorrowers_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_AddAuthorizedBorrowers_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_AddAuthorizedBorrowers_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_AddAuthorizedBorrowers_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_AddAuthorizedBorrowers_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{12}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AddAuthorizedBorrowers_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AddAuthorizedBorrowers_Request) GetSteamidBorrower() []uint64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.SteamidBorrower
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_AddAuthorizedBorrowers_Response struct {
|
|
||||||
SecondsToWait *int32 `protobuf:"varint,1,opt,name=seconds_to_wait" json:"seconds_to_wait,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AddAuthorizedBorrowers_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_AddAuthorizedBorrowers_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_AddAuthorizedBorrowers_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_AddAuthorizedBorrowers_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_AddAuthorizedBorrowers_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{13}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_AddAuthorizedBorrowers_Response) GetSecondsToWait() int32 {
|
|
||||||
if m != nil && m.SecondsToWait != nil {
|
|
||||||
return *m.SecondsToWait
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_RemoveAuthorizedBorrowers_Request struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
SteamidBorrower []uint64 `protobuf:"fixed64,2,rep,name=steamid_borrower" json:"steamid_borrower,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_RemoveAuthorizedBorrowers_Request) Reset() {
|
|
||||||
*m = CDeviceAuth_RemoveAuthorizedBorrowers_Request{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_RemoveAuthorizedBorrowers_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_RemoveAuthorizedBorrowers_Request) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_RemoveAuthorizedBorrowers_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{14}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_RemoveAuthorizedBorrowers_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_RemoveAuthorizedBorrowers_Request) GetSteamidBorrower() []uint64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.SteamidBorrower
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CDeviceAuth_RemoveAuthorizedBorrowers_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CDeviceAuth_RemoveAuthorizedBorrowers_Response) Reset() {
|
|
||||||
*m = CDeviceAuth_RemoveAuthorizedBorrowers_Response{}
|
|
||||||
}
|
|
||||||
func (m *CDeviceAuth_RemoveAuthorizedBorrowers_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CDeviceAuth_RemoveAuthorizedBorrowers_Response) ProtoMessage() {}
|
|
||||||
func (*CDeviceAuth_RemoveAuthorizedBorrowers_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return deviceauth_fileDescriptor0, []int{15}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetOwnAuthorizedDevices_Request)(nil), "CDeviceAuth_GetOwnAuthorizedDevices_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetOwnAuthorizedDevices_Response)(nil), "CDeviceAuth_GetOwnAuthorizedDevices_Response")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetOwnAuthorizedDevices_Response_Device)(nil), "CDeviceAuth_GetOwnAuthorizedDevices_Response.Device")
|
|
||||||
proto.RegisterType((*CDeviceAuth_AcceptAuthorizationRequest_Request)(nil), "CDeviceAuth_AcceptAuthorizationRequest_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_AcceptAuthorizationRequest_Response)(nil), "CDeviceAuth_AcceptAuthorizationRequest_Response")
|
|
||||||
proto.RegisterType((*CDeviceAuth_AuthorizeRemoteDevice_Request)(nil), "CDeviceAuth_AuthorizeRemoteDevice_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_AuthorizeRemoteDevice_Response)(nil), "CDeviceAuth_AuthorizeRemoteDevice_Response")
|
|
||||||
proto.RegisterType((*CDeviceAuth_DeauthorizeRemoteDevice_Request)(nil), "CDeviceAuth_DeauthorizeRemoteDevice_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_DeauthorizeRemoteDevice_Response)(nil), "CDeviceAuth_DeauthorizeRemoteDevice_Response")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetUsedAuthorizedDevices_Request)(nil), "CDeviceAuth_GetUsedAuthorizedDevices_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetUsedAuthorizedDevices_Response)(nil), "CDeviceAuth_GetUsedAuthorizedDevices_Response")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetUsedAuthorizedDevices_Response_Device)(nil), "CDeviceAuth_GetUsedAuthorizedDevices_Response.Device")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetAuthorizedBorrowers_Request)(nil), "CDeviceAuth_GetAuthorizedBorrowers_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetAuthorizedBorrowers_Response)(nil), "CDeviceAuth_GetAuthorizedBorrowers_Response")
|
|
||||||
proto.RegisterType((*CDeviceAuth_GetAuthorizedBorrowers_Response_Borrower)(nil), "CDeviceAuth_GetAuthorizedBorrowers_Response.Borrower")
|
|
||||||
proto.RegisterType((*CDeviceAuth_AddAuthorizedBorrowers_Request)(nil), "CDeviceAuth_AddAuthorizedBorrowers_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_AddAuthorizedBorrowers_Response)(nil), "CDeviceAuth_AddAuthorizedBorrowers_Response")
|
|
||||||
proto.RegisterType((*CDeviceAuth_RemoveAuthorizedBorrowers_Request)(nil), "CDeviceAuth_RemoveAuthorizedBorrowers_Request")
|
|
||||||
proto.RegisterType((*CDeviceAuth_RemoveAuthorizedBorrowers_Response)(nil), "CDeviceAuth_RemoveAuthorizedBorrowers_Response")
|
|
||||||
}
|
|
||||||
|
|
||||||
var deviceauth_fileDescriptor0 = []byte{
|
|
||||||
// 934 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x56, 0xdf, 0x4e, 0x3b, 0x45,
|
|
||||||
0x14, 0xce, 0xb6, 0x50, 0x60, 0x10, 0x91, 0x51, 0xa0, 0xec, 0x85, 0x4e, 0x56, 0x2f, 0x10, 0xca,
|
|
||||||
0x80, 0x04, 0xe3, 0xff, 0x3f, 0x20, 0xa2, 0x17, 0x26, 0x26, 0x18, 0xa3, 0x72, 0xb3, 0x99, 0xee,
|
|
||||||
0x0e, 0x74, 0x62, 0xbb, 0xbb, 0xee, 0x4c, 0x69, 0xf0, 0x8a, 0x98, 0xf8, 0x12, 0xfa, 0x06, 0x5e,
|
|
||||||
0x19, 0x13, 0xa2, 0x89, 0x5e, 0xf8, 0x0e, 0xbe, 0x8d, 0x57, 0xbf, 0xb3, 0xb3, 0xb3, 0x85, 0x6d,
|
|
||||||
0x77, 0x4b, 0xb7, 0xe1, 0xaa, 0x9b, 0x73, 0xce, 0x9c, 0xf9, 0xce, 0x99, 0xf3, 0x7d, 0xa7, 0x68,
|
|
||||||
0x47, 0x2a, 0xce, 0x7a, 0x3d, 0x2e, 0x25, 0xbb, 0xe2, 0xd2, 0xf5, 0xf9, 0xb5, 0xf0, 0x38, 0xeb,
|
|
||||||
0xab, 0x0e, 0xd5, 0x0e, 0xaf, 0x2b, 0x78, 0xa0, 0x68, 0x14, 0x87, 0x2a, 0xb4, 0x5b, 0xf9, 0xd8,
|
|
||||||
0x7e, 0x20, 0x2e, 0x05, 0xf7, 0xdd, 0x36, 0x93, 0x7c, 0x3c, 0xda, 0xf9, 0x16, 0xed, 0x7e, 0x72,
|
|
||||||
0xaa, 0xd3, 0x1d, 0x43, 0x3a, 0xf7, 0x33, 0xae, 0xbe, 0x1c, 0x04, 0xc9, 0x67, 0x18, 0x8b, 0x1f,
|
|
||||||
0xb9, 0x9f, 0xba, 0xa4, 0x7b, 0xce, 0x7f, 0xe8, 0x73, 0xa9, 0xf0, 0x2a, 0x5a, 0xd0, 0x39, 0x84,
|
|
||||||
0xdf, 0xb4, 0x88, 0xb5, 0xdd, 0xc0, 0x4d, 0xf4, 0x82, 0x08, 0xbc, 0x6e, 0xdf, 0xe7, 0xae, 0xc7,
|
|
||||||
0x02, 0x8f, 0x77, 0xb9, 0xdf, 0xac, 0x81, 0x67, 0xd1, 0xf9, 0xab, 0x86, 0x5a, 0xd3, 0xa5, 0x96,
|
|
||||||
0x51, 0x18, 0x48, 0x8e, 0x3f, 0x45, 0x0b, 0x69, 0x61, 0x12, 0x72, 0xd7, 0xb7, 0x97, 0x0f, 0x8f,
|
|
||||||
0x68, 0x95, 0xf3, 0x34, 0x35, 0xd8, 0xff, 0x5a, 0xa8, 0x91, 0x7e, 0xe2, 0x2d, 0xb4, 0x96, 0x34,
|
|
||||||
0xc9, 0xf4, 0xcb, 0x55, 0xe1, 0xf7, 0x3c, 0x30, 0xb8, 0x5f, 0x44, 0xcb, 0xc6, 0x1a, 0xb0, 0x1e,
|
|
||||||
0xd7, 0x90, 0x97, 0x30, 0x46, 0x48, 0x48, 0x37, 0xe2, 0x81, 0x2f, 0x82, 0xab, 0x66, 0x3d, 0x29,
|
|
||||||
0x23, 0x09, 0x04, 0xdb, 0xb0, 0xb6, 0x39, 0x6d, 0xdc, 0x40, 0xcf, 0x77, 0x99, 0x54, 0xae, 0x12,
|
|
||||||
0x3d, 0xee, 0xf6, 0x25, 0xd8, 0xe7, 0xc1, 0xbe, 0x92, 0x74, 0x43, 0xdb, 0xdb, 0x61, 0x1c, 0x87,
|
|
||||||
0x03, 0x1e, 0xbb, 0xd0, 0xa7, 0x86, 0xbe, 0x6f, 0x13, 0xad, 0x6a, 0x0f, 0x8b, 0x22, 0x37, 0xea,
|
|
||||||
0xb2, 0x1b, 0x38, 0xb2, 0xa0, 0x8f, 0xa4, 0x77, 0x76, 0x45, 0x4f, 0x28, 0xb0, 0x2d, 0xea, 0xd6,
|
|
||||||
0xfd, 0x6c, 0xa1, 0x5c, 0xe9, 0xc7, 0x9e, 0xc7, 0x23, 0x95, 0x95, 0xce, 0x94, 0x08, 0x03, 0xf3,
|
|
||||||
0x20, 0xe5, 0x0f, 0x53, 0x58, 0x7b, 0x4d, 0xbb, 0xd6, 0xd0, 0x92, 0x76, 0x79, 0xa1, 0xcf, 0x75,
|
|
||||||
0x95, 0x0d, 0xfc, 0x12, 0x7a, 0xee, 0x32, 0x0e, 0x7b, 0x6e, 0x96, 0x23, 0x29, 0xb3, 0xe1, 0xbc,
|
|
||||||
0x81, 0xf6, 0xa7, 0x86, 0x91, 0x3e, 0x82, 0xf3, 0x0d, 0x7a, 0x3d, 0x77, 0x24, 0x7b, 0xae, 0x73,
|
|
||||||
0xde, 0x0b, 0x15, 0x4f, 0x3d, 0xb3, 0x80, 0x76, 0x5a, 0x68, 0x67, 0x9a, 0xc4, 0x06, 0xc6, 0x77,
|
|
||||||
0xf9, 0xb1, 0x3e, 0xd5, 0x64, 0x79, 0x1a, 0x20, 0x34, 0x3f, 0xd6, 0xe5, 0xa9, 0x0d, 0x94, 0x8f,
|
|
||||||
0xc6, 0x68, 0xf0, 0x35, 0x0c, 0xcc, 0xf4, 0x14, 0x73, 0xfe, 0xb7, 0xd0, 0xde, 0x94, 0x19, 0x0c,
|
|
||||||
0x93, 0xce, 0x46, 0x99, 0xf4, 0x26, 0xad, 0x94, 0x20, 0xa3, 0xd2, 0xed, 0xec, 0x54, 0x5a, 0x47,
|
|
||||||
0x2b, 0xe1, 0x20, 0x00, 0x06, 0x64, 0xb5, 0xa4, 0x73, 0x36, 0x4e, 0x9c, 0x39, 0xcd, 0x82, 0x02,
|
|
||||||
0x7a, 0x68, 0x46, 0x39, 0x51, 0xfe, 0xd9, 0x01, 0xfa, 0x3d, 0xec, 0x13, 0xc3, 0xb2, 0x59, 0xe4,
|
|
||||||
0x29, 0xb9, 0x31, 0xf3, 0xe4, 0x08, 0xef, 0xfc, 0x67, 0x8d, 0x49, 0x62, 0xf1, 0x95, 0xa6, 0xd9,
|
|
||||||
0x9f, 0xa3, 0xa5, 0x8c, 0xee, 0xa5, 0xed, 0x9e, 0x94, 0x80, 0x66, 0x26, 0xfb, 0x02, 0x2d, 0x66,
|
|
||||||
0xdf, 0xe3, 0x95, 0xe4, 0xb5, 0xa9, 0x56, 0xa4, 0x4d, 0xa9, 0x60, 0x01, 0x95, 0x75, 0x77, 0xbd,
|
|
||||||
0x98, 0x33, 0x95, 0x35, 0x18, 0x78, 0x99, 0xa7, 0x8f, 0xef, 0x57, 0xed, 0xa3, 0x31, 0x0c, 0xb5,
|
|
||||||
0x0d, 0x30, 0xd4, 0x61, 0x3a, 0xcf, 0xf2, 0xdd, 0x2a, 0x4d, 0x6c, 0xba, 0x05, 0x6d, 0x97, 0xdc,
|
|
||||||
0x0b, 0x03, 0x5f, 0xc2, 0x0c, 0xb9, 0x03, 0x26, 0x94, 0xbe, 0x61, 0xde, 0xb9, 0xc8, 0x0f, 0x79,
|
|
||||||
0xc2, 0xa5, 0x6b, 0xfe, 0x44, 0x18, 0x0f, 0xf2, 0x72, 0x3a, 0x29, 0x77, 0x0a, 0xf3, 0xf0, 0xcf,
|
|
||||||
0x65, 0x84, 0xee, 0x4f, 0xe0, 0x5f, 0x2c, 0xb4, 0x59, 0xb2, 0x7f, 0x70, 0x8b, 0x56, 0x58, 0xa0,
|
|
||||||
0xf6, 0x5e, 0xa5, 0x9d, 0xe6, 0x38, 0x3f, 0xdd, 0x35, 0x5f, 0x86, 0x28, 0xd2, 0x15, 0x52, 0x91,
|
|
||||||
0xf0, 0x92, 0x0c, 0xc5, 0xc6, 0x27, 0x86, 0xe2, 0xf8, 0xce, 0x42, 0x76, 0xb9, 0x34, 0xe3, 0xfd,
|
|
||||||
0x8a, 0xab, 0xc4, 0x3e, 0xa0, 0x55, 0x45, 0xff, 0x08, 0x50, 0x1e, 0xa4, 0x81, 0x84, 0x05, 0x43,
|
|
||||||
0x8c, 0x3a, 0x98, 0xc4, 0x69, 0x34, 0x69, 0xdf, 0x80, 0x2f, 0x54, 0x1d, 0x1e, 0x13, 0x20, 0x7e,
|
|
||||||
0x2c, 0xf1, 0x6f, 0x16, 0x5a, 0x2f, 0x94, 0x71, 0xbc, 0x43, 0xa7, 0xde, 0x21, 0xf6, 0x2e, 0xad,
|
|
||||||
0xb0, 0x16, 0xde, 0x06, 0xa0, 0x47, 0xc3, 0x18, 0x02, 0x0a, 0x05, 0xf0, 0x92, 0x40, 0xd3, 0x4c,
|
|
||||||
0xa2, 0x3a, 0x4c, 0x91, 0x0e, 0x93, 0xc4, 0x10, 0x2d, 0x43, 0x8f, 0x7f, 0x85, 0x09, 0x28, 0x91,
|
|
||||||
0xfa, 0x91, 0x09, 0x78, 0x64, 0xd7, 0x8c, 0x4c, 0xc0, 0xa3, 0xeb, 0xe3, 0x55, 0x80, 0xfc, 0xca,
|
|
||||||
0x39, 0xbf, 0x06, 0xc1, 0xd5, 0x78, 0x0d, 0xd0, 0x5c, 0x8f, 0xf1, 0xdf, 0x16, 0x6a, 0x96, 0xa9,
|
|
||||||
0x3a, 0xde, 0xa3, 0x55, 0xf6, 0x8f, 0x4d, 0xab, 0xed, 0x0a, 0xe7, 0x63, 0x00, 0xf8, 0xfe, 0xe4,
|
|
||||||
0x11, 0xd5, 0x0f, 0x4e, 0x52, 0x5d, 0x27, 0x86, 0x9b, 0x3e, 0xb9, 0x82, 0x6d, 0x21, 0x09, 0xa0,
|
|
||||||
0xff, 0xc3, 0x42, 0x1b, 0xc5, 0x22, 0x89, 0x77, 0xe9, 0xf4, 0xea, 0x6f, 0xb7, 0xaa, 0xc8, 0xae,
|
|
||||||
0xf3, 0x01, 0xe0, 0x7e, 0xe7, 0x21, 0x6e, 0x3d, 0x95, 0xe9, 0x04, 0x80, 0xa4, 0x1a, 0x9c, 0x80,
|
|
||||||
0xef, 0xe1, 0x48, 0x0f, 0x6b, 0xc2, 0xbf, 0x03, 0xe8, 0x62, 0xb1, 0x1b, 0x01, 0x3d, 0x59, 0x6a,
|
|
||||||
0x47, 0x40, 0x3f, 0x22, 0x9f, 0xce, 0x7b, 0x00, 0xfa, 0x2d, 0x08, 0x2a, 0x07, 0x6b, 0xfe, 0x49,
|
|
||||||
0x16, 0x09, 0xc5, 0x3f, 0x16, 0xda, 0x2a, 0xd5, 0x3e, 0x4c, 0x69, 0x25, 0xfd, 0xb5, 0xf7, 0x2b,
|
|
||||||
0x6a, 0xaa, 0xf3, 0x21, 0x60, 0x7f, 0x37, 0x8d, 0x9b, 0x05, 0xbe, 0xfd, 0x1a, 0x9c, 0x27, 0x5f,
|
|
||||||
0x88, 0x76, 0xcc, 0xe2, 0x1b, 0xf2, 0x55, 0x87, 0xc5, 0x09, 0x3f, 0x25, 0x57, 0x0a, 0x7e, 0x25,
|
|
||||||
0x7c, 0xc4, 0x49, 0xd8, 0x49, 0xfd, 0xd6, 0xb2, 0x9e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x27, 0xc5,
|
|
||||||
0x15, 0xba, 0x30, 0x0d, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
850
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/gamenotifications.pb.go
generated
vendored
850
vendor/github.com/Philipp15b/go-steam/protocol/protobuf/unified/gamenotifications.pb.go
generated
vendored
@@ -1,850 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go.
|
|
||||||
// source: steammessages_gamenotifications.steamclient.proto
|
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
package unified
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import fmt "fmt"
|
|
||||||
import math "math"
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
type CGameNotifications_Variable struct {
|
|
||||||
Key *string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"`
|
|
||||||
Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Variable) Reset() { *m = CGameNotifications_Variable{} }
|
|
||||||
func (m *CGameNotifications_Variable) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_Variable) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_Variable) Descriptor() ([]byte, []int) { return gamenotifications_fileDescriptor0, []int{0} }
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Variable) GetKey() string {
|
|
||||||
if m != nil && m.Key != nil {
|
|
||||||
return *m.Key
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Variable) GetValue() string {
|
|
||||||
if m != nil && m.Value != nil {
|
|
||||||
return *m.Value
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_LocalizedText struct {
|
|
||||||
Token *string `protobuf:"bytes,1,opt,name=token" json:"token,omitempty"`
|
|
||||||
Variables []*CGameNotifications_Variable `protobuf:"bytes,2,rep,name=variables" json:"variables,omitempty"`
|
|
||||||
RenderedText *string `protobuf:"bytes,3,opt,name=rendered_text" json:"rendered_text,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_LocalizedText) Reset() { *m = CGameNotifications_LocalizedText{} }
|
|
||||||
func (m *CGameNotifications_LocalizedText) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_LocalizedText) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_LocalizedText) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_LocalizedText) GetToken() string {
|
|
||||||
if m != nil && m.Token != nil {
|
|
||||||
return *m.Token
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_LocalizedText) GetVariables() []*CGameNotifications_Variable {
|
|
||||||
if m != nil {
|
|
||||||
return m.Variables
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_LocalizedText) GetRenderedText() string {
|
|
||||||
if m != nil && m.RenderedText != nil {
|
|
||||||
return *m.RenderedText
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_UserStatus struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
State *string `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"`
|
|
||||||
Title *CGameNotifications_LocalizedText `protobuf:"bytes,3,opt,name=title" json:"title,omitempty"`
|
|
||||||
Message *CGameNotifications_LocalizedText `protobuf:"bytes,4,opt,name=message" json:"message,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UserStatus) Reset() { *m = CGameNotifications_UserStatus{} }
|
|
||||||
func (m *CGameNotifications_UserStatus) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_UserStatus) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_UserStatus) Descriptor() ([]byte, []int) { return gamenotifications_fileDescriptor0, []int{2} }
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UserStatus) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UserStatus) GetState() string {
|
|
||||||
if m != nil && m.State != nil {
|
|
||||||
return *m.State
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UserStatus) GetTitle() *CGameNotifications_LocalizedText {
|
|
||||||
if m != nil {
|
|
||||||
return m.Title
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UserStatus) GetMessage() *CGameNotifications_LocalizedText {
|
|
||||||
if m != nil {
|
|
||||||
return m.Message
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_CreateSession_Request struct {
|
|
||||||
Appid *uint32 `protobuf:"varint,1,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
Context *uint64 `protobuf:"varint,2,opt,name=context" json:"context,omitempty"`
|
|
||||||
Title *CGameNotifications_LocalizedText `protobuf:"bytes,3,opt,name=title" json:"title,omitempty"`
|
|
||||||
Users []*CGameNotifications_UserStatus `protobuf:"bytes,4,rep,name=users" json:"users,omitempty"`
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,5,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Request) Reset() {
|
|
||||||
*m = CGameNotifications_CreateSession_Request{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_CreateSession_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_CreateSession_Request) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_CreateSession_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{3}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Request) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Request) GetContext() uint64 {
|
|
||||||
if m != nil && m.Context != nil {
|
|
||||||
return *m.Context
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Request) GetTitle() *CGameNotifications_LocalizedText {
|
|
||||||
if m != nil {
|
|
||||||
return m.Title
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Request) GetUsers() []*CGameNotifications_UserStatus {
|
|
||||||
if m != nil {
|
|
||||||
return m.Users
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_CreateSession_Response struct {
|
|
||||||
Sessionid *uint64 `protobuf:"varint,1,opt,name=sessionid" json:"sessionid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Response) Reset() {
|
|
||||||
*m = CGameNotifications_CreateSession_Response{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_CreateSession_Response) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_CreateSession_Response) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_CreateSession_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{4}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_CreateSession_Response) GetSessionid() uint64 {
|
|
||||||
if m != nil && m.Sessionid != nil {
|
|
||||||
return *m.Sessionid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_DeleteSession_Request struct {
|
|
||||||
Sessionid *uint64 `protobuf:"varint,1,opt,name=sessionid" json:"sessionid,omitempty"`
|
|
||||||
Appid *uint32 `protobuf:"varint,2,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,3,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_DeleteSession_Request) Reset() {
|
|
||||||
*m = CGameNotifications_DeleteSession_Request{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_DeleteSession_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_DeleteSession_Request) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_DeleteSession_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{5}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_DeleteSession_Request) GetSessionid() uint64 {
|
|
||||||
if m != nil && m.Sessionid != nil {
|
|
||||||
return *m.Sessionid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_DeleteSession_Request) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_DeleteSession_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_DeleteSession_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_DeleteSession_Response) Reset() {
|
|
||||||
*m = CGameNotifications_DeleteSession_Response{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_DeleteSession_Response) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_DeleteSession_Response) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_DeleteSession_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{6}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_UpdateSession_Request struct {
|
|
||||||
Sessionid *uint64 `protobuf:"varint,1,opt,name=sessionid" json:"sessionid,omitempty"`
|
|
||||||
Appid *uint32 `protobuf:"varint,2,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
Title *CGameNotifications_LocalizedText `protobuf:"bytes,3,opt,name=title" json:"title,omitempty"`
|
|
||||||
Users []*CGameNotifications_UserStatus `protobuf:"bytes,4,rep,name=users" json:"users,omitempty"`
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,6,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateSession_Request) Reset() {
|
|
||||||
*m = CGameNotifications_UpdateSession_Request{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_UpdateSession_Request) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_UpdateSession_Request) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_UpdateSession_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{7}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateSession_Request) GetSessionid() uint64 {
|
|
||||||
if m != nil && m.Sessionid != nil {
|
|
||||||
return *m.Sessionid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateSession_Request) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateSession_Request) GetTitle() *CGameNotifications_LocalizedText {
|
|
||||||
if m != nil {
|
|
||||||
return m.Title
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateSession_Request) GetUsers() []*CGameNotifications_UserStatus {
|
|
||||||
if m != nil {
|
|
||||||
return m.Users
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateSession_Request) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_UpdateSession_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateSession_Response) Reset() {
|
|
||||||
*m = CGameNotifications_UpdateSession_Response{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_UpdateSession_Response) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_UpdateSession_Response) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_UpdateSession_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{8}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_EnumerateSessions_Request struct {
|
|
||||||
Appid *uint32 `protobuf:"varint,1,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
IncludeAllUserMessages *bool `protobuf:"varint,3,opt,name=include_all_user_messages" json:"include_all_user_messages,omitempty"`
|
|
||||||
IncludeAuthUserMessage *bool `protobuf:"varint,4,opt,name=include_auth_user_message" json:"include_auth_user_message,omitempty"`
|
|
||||||
Language *string `protobuf:"bytes,5,opt,name=language" json:"language,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Request) Reset() {
|
|
||||||
*m = CGameNotifications_EnumerateSessions_Request{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_EnumerateSessions_Request) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_EnumerateSessions_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{9}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Request) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Request) GetIncludeAllUserMessages() bool {
|
|
||||||
if m != nil && m.IncludeAllUserMessages != nil {
|
|
||||||
return *m.IncludeAllUserMessages
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Request) GetIncludeAuthUserMessage() bool {
|
|
||||||
if m != nil && m.IncludeAuthUserMessage != nil {
|
|
||||||
return *m.IncludeAuthUserMessage
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Request) GetLanguage() string {
|
|
||||||
if m != nil && m.Language != nil {
|
|
||||||
return *m.Language
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_Session struct {
|
|
||||||
Sessionid *uint64 `protobuf:"varint,1,opt,name=sessionid" json:"sessionid,omitempty"`
|
|
||||||
Appid *uint64 `protobuf:"varint,2,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
Context *uint64 `protobuf:"varint,3,opt,name=context" json:"context,omitempty"`
|
|
||||||
Title *CGameNotifications_LocalizedText `protobuf:"bytes,4,opt,name=title" json:"title,omitempty"`
|
|
||||||
TimeCreated *uint32 `protobuf:"varint,5,opt,name=time_created" json:"time_created,omitempty"`
|
|
||||||
TimeUpdated *uint32 `protobuf:"varint,6,opt,name=time_updated" json:"time_updated,omitempty"`
|
|
||||||
UserStatus []*CGameNotifications_UserStatus `protobuf:"bytes,7,rep,name=user_status" json:"user_status,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) Reset() { *m = CGameNotifications_Session{} }
|
|
||||||
func (m *CGameNotifications_Session) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*CGameNotifications_Session) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_Session) Descriptor() ([]byte, []int) { return gamenotifications_fileDescriptor0, []int{10} }
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) GetSessionid() uint64 {
|
|
||||||
if m != nil && m.Sessionid != nil {
|
|
||||||
return *m.Sessionid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) GetAppid() uint64 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) GetContext() uint64 {
|
|
||||||
if m != nil && m.Context != nil {
|
|
||||||
return *m.Context
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) GetTitle() *CGameNotifications_LocalizedText {
|
|
||||||
if m != nil {
|
|
||||||
return m.Title
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) GetTimeCreated() uint32 {
|
|
||||||
if m != nil && m.TimeCreated != nil {
|
|
||||||
return *m.TimeCreated
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) GetTimeUpdated() uint32 {
|
|
||||||
if m != nil && m.TimeUpdated != nil {
|
|
||||||
return *m.TimeUpdated
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_Session) GetUserStatus() []*CGameNotifications_UserStatus {
|
|
||||||
if m != nil {
|
|
||||||
return m.UserStatus
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_EnumerateSessions_Response struct {
|
|
||||||
Sessions []*CGameNotifications_Session `protobuf:"bytes,1,rep,name=sessions" json:"sessions,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Response) Reset() {
|
|
||||||
*m = CGameNotifications_EnumerateSessions_Response{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_EnumerateSessions_Response) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_EnumerateSessions_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{11}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_EnumerateSessions_Response) GetSessions() []*CGameNotifications_Session {
|
|
||||||
if m != nil {
|
|
||||||
return m.Sessions
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_GetSessionDetails_Request struct {
|
|
||||||
Sessions []*CGameNotifications_GetSessionDetails_Request_RequestedSession `protobuf:"bytes,1,rep,name=sessions" json:"sessions,omitempty"`
|
|
||||||
Appid *uint32 `protobuf:"varint,2,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
Language *string `protobuf:"bytes,3,opt,name=language" json:"language,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request) Reset() {
|
|
||||||
*m = CGameNotifications_GetSessionDetails_Request{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_GetSessionDetails_Request) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_GetSessionDetails_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{12}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request) GetSessions() []*CGameNotifications_GetSessionDetails_Request_RequestedSession {
|
|
||||||
if m != nil {
|
|
||||||
return m.Sessions
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request) GetLanguage() string {
|
|
||||||
if m != nil && m.Language != nil {
|
|
||||||
return *m.Language
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_GetSessionDetails_Request_RequestedSession struct {
|
|
||||||
Sessionid *uint64 `protobuf:"varint,1,opt,name=sessionid" json:"sessionid,omitempty"`
|
|
||||||
IncludeAuthUserMessage *bool `protobuf:"varint,3,opt,name=include_auth_user_message" json:"include_auth_user_message,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request_RequestedSession) Reset() {
|
|
||||||
*m = CGameNotifications_GetSessionDetails_Request_RequestedSession{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request_RequestedSession) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_GetSessionDetails_Request_RequestedSession) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_GetSessionDetails_Request_RequestedSession) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{12, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request_RequestedSession) GetSessionid() uint64 {
|
|
||||||
if m != nil && m.Sessionid != nil {
|
|
||||||
return *m.Sessionid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Request_RequestedSession) GetIncludeAuthUserMessage() bool {
|
|
||||||
if m != nil && m.IncludeAuthUserMessage != nil {
|
|
||||||
return *m.IncludeAuthUserMessage
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_GetSessionDetails_Response struct {
|
|
||||||
Sessions []*CGameNotifications_Session `protobuf:"bytes,1,rep,name=sessions" json:"sessions,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Response) Reset() {
|
|
||||||
*m = CGameNotifications_GetSessionDetails_Response{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_GetSessionDetails_Response) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_GetSessionDetails_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{13}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_GetSessionDetails_Response) GetSessions() []*CGameNotifications_Session {
|
|
||||||
if m != nil {
|
|
||||||
return m.Sessions
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GameNotificationSettings struct {
|
|
||||||
Appid *uint32 `protobuf:"varint,1,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
AllowNotifications *bool `protobuf:"varint,2,opt,name=allow_notifications" json:"allow_notifications,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GameNotificationSettings) Reset() { *m = GameNotificationSettings{} }
|
|
||||||
func (m *GameNotificationSettings) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*GameNotificationSettings) ProtoMessage() {}
|
|
||||||
func (*GameNotificationSettings) Descriptor() ([]byte, []int) { return gamenotifications_fileDescriptor0, []int{14} }
|
|
||||||
|
|
||||||
func (m *GameNotificationSettings) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GameNotificationSettings) GetAllowNotifications() bool {
|
|
||||||
if m != nil && m.AllowNotifications != nil {
|
|
||||||
return *m.AllowNotifications
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_UpdateNotificationSettings_Request struct {
|
|
||||||
GameNotificationSettings []*GameNotificationSettings `protobuf:"bytes,1,rep,name=game_notification_settings" json:"game_notification_settings,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateNotificationSettings_Request) Reset() {
|
|
||||||
*m = CGameNotifications_UpdateNotificationSettings_Request{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_UpdateNotificationSettings_Request) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_UpdateNotificationSettings_Request) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_UpdateNotificationSettings_Request) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{15}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateNotificationSettings_Request) GetGameNotificationSettings() []*GameNotificationSettings {
|
|
||||||
if m != nil {
|
|
||||||
return m.GameNotificationSettings
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_UpdateNotificationSettings_Response struct {
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_UpdateNotificationSettings_Response) Reset() {
|
|
||||||
*m = CGameNotifications_UpdateNotificationSettings_Response{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_UpdateNotificationSettings_Response) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_UpdateNotificationSettings_Response) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_UpdateNotificationSettings_Response) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{16}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_OnNotificationsRequested_Notification struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
Appid *uint32 `protobuf:"varint,2,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnNotificationsRequested_Notification) Reset() {
|
|
||||||
*m = CGameNotifications_OnNotificationsRequested_Notification{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_OnNotificationsRequested_Notification) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_OnNotificationsRequested_Notification) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_OnNotificationsRequested_Notification) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{17}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnNotificationsRequested_Notification) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnNotificationsRequested_Notification) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CGameNotifications_OnUserStatusChanged_Notification struct {
|
|
||||||
Steamid *uint64 `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"`
|
|
||||||
Sessionid *uint64 `protobuf:"varint,2,opt,name=sessionid" json:"sessionid,omitempty"`
|
|
||||||
Appid *uint32 `protobuf:"varint,3,opt,name=appid" json:"appid,omitempty"`
|
|
||||||
Status *CGameNotifications_UserStatus `protobuf:"bytes,4,opt,name=status" json:"status,omitempty"`
|
|
||||||
Removed *bool `protobuf:"varint,5,opt,name=removed" json:"removed,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnUserStatusChanged_Notification) Reset() {
|
|
||||||
*m = CGameNotifications_OnUserStatusChanged_Notification{}
|
|
||||||
}
|
|
||||||
func (m *CGameNotifications_OnUserStatusChanged_Notification) String() string {
|
|
||||||
return proto.CompactTextString(m)
|
|
||||||
}
|
|
||||||
func (*CGameNotifications_OnUserStatusChanged_Notification) ProtoMessage() {}
|
|
||||||
func (*CGameNotifications_OnUserStatusChanged_Notification) Descriptor() ([]byte, []int) {
|
|
||||||
return gamenotifications_fileDescriptor0, []int{18}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnUserStatusChanged_Notification) GetSteamid() uint64 {
|
|
||||||
if m != nil && m.Steamid != nil {
|
|
||||||
return *m.Steamid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnUserStatusChanged_Notification) GetSessionid() uint64 {
|
|
||||||
if m != nil && m.Sessionid != nil {
|
|
||||||
return *m.Sessionid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnUserStatusChanged_Notification) GetAppid() uint32 {
|
|
||||||
if m != nil && m.Appid != nil {
|
|
||||||
return *m.Appid
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnUserStatusChanged_Notification) GetStatus() *CGameNotifications_UserStatus {
|
|
||||||
if m != nil {
|
|
||||||
return m.Status
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CGameNotifications_OnUserStatusChanged_Notification) GetRemoved() bool {
|
|
||||||
if m != nil && m.Removed != nil {
|
|
||||||
return *m.Removed
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterType((*CGameNotifications_Variable)(nil), "CGameNotifications_Variable")
|
|
||||||
proto.RegisterType((*CGameNotifications_LocalizedText)(nil), "CGameNotifications_LocalizedText")
|
|
||||||
proto.RegisterType((*CGameNotifications_UserStatus)(nil), "CGameNotifications_UserStatus")
|
|
||||||
proto.RegisterType((*CGameNotifications_CreateSession_Request)(nil), "CGameNotifications_CreateSession_Request")
|
|
||||||
proto.RegisterType((*CGameNotifications_CreateSession_Response)(nil), "CGameNotifications_CreateSession_Response")
|
|
||||||
proto.RegisterType((*CGameNotifications_DeleteSession_Request)(nil), "CGameNotifications_DeleteSession_Request")
|
|
||||||
proto.RegisterType((*CGameNotifications_DeleteSession_Response)(nil), "CGameNotifications_DeleteSession_Response")
|
|
||||||
proto.RegisterType((*CGameNotifications_UpdateSession_Request)(nil), "CGameNotifications_UpdateSession_Request")
|
|
||||||
proto.RegisterType((*CGameNotifications_UpdateSession_Response)(nil), "CGameNotifications_UpdateSession_Response")
|
|
||||||
proto.RegisterType((*CGameNotifications_EnumerateSessions_Request)(nil), "CGameNotifications_EnumerateSessions_Request")
|
|
||||||
proto.RegisterType((*CGameNotifications_Session)(nil), "CGameNotifications_Session")
|
|
||||||
proto.RegisterType((*CGameNotifications_EnumerateSessions_Response)(nil), "CGameNotifications_EnumerateSessions_Response")
|
|
||||||
proto.RegisterType((*CGameNotifications_GetSessionDetails_Request)(nil), "CGameNotifications_GetSessionDetails_Request")
|
|
||||||
proto.RegisterType((*CGameNotifications_GetSessionDetails_Request_RequestedSession)(nil), "CGameNotifications_GetSessionDetails_Request.RequestedSession")
|
|
||||||
proto.RegisterType((*CGameNotifications_GetSessionDetails_Response)(nil), "CGameNotifications_GetSessionDetails_Response")
|
|
||||||
proto.RegisterType((*GameNotificationSettings)(nil), "GameNotificationSettings")
|
|
||||||
proto.RegisterType((*CGameNotifications_UpdateNotificationSettings_Request)(nil), "CGameNotifications_UpdateNotificationSettings_Request")
|
|
||||||
proto.RegisterType((*CGameNotifications_UpdateNotificationSettings_Response)(nil), "CGameNotifications_UpdateNotificationSettings_Response")
|
|
||||||
proto.RegisterType((*CGameNotifications_OnNotificationsRequested_Notification)(nil), "CGameNotifications_OnNotificationsRequested_Notification")
|
|
||||||
proto.RegisterType((*CGameNotifications_OnUserStatusChanged_Notification)(nil), "CGameNotifications_OnUserStatusChanged_Notification")
|
|
||||||
}
|
|
||||||
|
|
||||||
var gamenotifications_fileDescriptor0 = []byte{
|
|
||||||
// 2245 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x59, 0xcd, 0x8f, 0x1c, 0x47,
|
|
||||||
0x15, 0x57, 0xef, 0xec, 0x7a, 0xd7, 0x65, 0x2c, 0x91, 0x0e, 0x12, 0x93, 0xb1, 0xe3, 0xb4, 0x3b,
|
|
||||||
0x38, 0xde, 0x8d, 0x77, 0xcb, 0x78, 0x43, 0xfc, 0x01, 0x24, 0xc2, 0xbd, 0x8e, 0x4c, 0x24, 0xb3,
|
|
||||||
0x49, 0xbc, 0x9b, 0x60, 0x21, 0xc4, 0xa8, 0xa6, 0xbb, 0x66, 0xa7, 0xb3, 0x3d, 0xdd, 0x43, 0x57,
|
|
||||||
0xf5, 0x6e, 0x36, 0x07, 0x82, 0xcc, 0xd7, 0x09, 0x82, 0x48, 0x22, 0x40, 0x48, 0x91, 0x90, 0x50,
|
|
||||||
0xc4, 0x81, 0x0b, 0x87, 0x1c, 0x41, 0x48, 0x91, 0x38, 0x72, 0xcc, 0x15, 0xce, 0xfc, 0x15, 0xbc,
|
|
||||||
0xfa, 0xec, 0xee, 0x99, 0x1e, 0xef, 0xcc, 0x22, 0x11, 0x71, 0xb1, 0x3c, 0x5d, 0xf5, 0xde, 0xfb,
|
|
||||||
0xd5, 0x7b, 0xbf, 0xf7, 0x51, 0xb5, 0xe8, 0x1a, 0xe3, 0x94, 0x0c, 0x87, 0x94, 0x31, 0xb2, 0x47,
|
|
||||||
0x59, 0x77, 0x8f, 0x0c, 0x69, 0x9a, 0xf1, 0xb8, 0x1f, 0x87, 0x84, 0xc7, 0x59, 0xca, 0xb0, 0x5c,
|
|
||||||
0x0f, 0x93, 0x98, 0xa6, 0x1c, 0x8f, 0xf2, 0x8c, 0x67, 0x9d, 0xf5, 0xba, 0x48, 0x91, 0xc2, 0x6e,
|
|
||||||
0x1a, 0x75, 0x7b, 0x84, 0xd1, 0xc9, 0xdd, 0xfe, 0xbf, 0x16, 0xd0, 0xb9, 0xad, 0xbb, 0xa0, 0x76,
|
|
||||||
0xbb, 0xaa, 0xb6, 0xfb, 0x06, 0xc9, 0x63, 0xd2, 0x4b, 0xa8, 0xfb, 0x91, 0x83, 0x5a, 0xfb, 0xf4,
|
|
||||||
0xa8, 0xed, 0x78, 0xce, 0xea, 0xe9, 0xe0, 0x37, 0xce, 0xc3, 0x8f, 0xdb, 0xef, 0x39, 0xbb, 0x03,
|
|
||||||
0xea, 0xa5, 0x20, 0xe3, 0x65, 0x7d, 0x8f, 0xc3, 0xff, 0x0f, 0xf4, 0x6e, 0x2f, 0x4e, 0xe5, 0xef,
|
|
||||||
0x24, 0x0b, 0x49, 0x12, 0xbf, 0x4d, 0x23, 0x8f, 0xd3, 0xb7, 0xb8, 0xb7, 0xb1, 0xe1, 0x91, 0xf4,
|
|
||||||
0xe8, 0x70, 0x40, 0x73, 0x0a, 0xcb, 0x84, 0x7b, 0x97, 0x8c, 0x80, 0x50, 0x72, 0xc9, 0x8b, 0x99,
|
|
||||||
0xd7, 0xcf, 0x8a, 0x34, 0xf2, 0x0e, 0x63, 0x3e, 0xd0, 0x2a, 0xa4, 0x60, 0xcc, 0xe1, 0x53, 0x92,
|
|
||||||
0x78, 0x3d, 0xea, 0xb1, 0xa2, 0xc7, 0x78, 0xcc, 0x8b, 0x88, 0xaa, 0x6d, 0x72, 0xd3, 0x5e, 0x7c,
|
|
||||||
0x40, 0x53, 0xb0, 0x9e, 0x14, 0xd4, 0xfd, 0xb5, 0x83, 0x96, 0xe4, 0xff, 0xda, 0x0b, 0x12, 0xea,
|
|
||||||
0xcf, 0x04, 0xd4, 0x87, 0x12, 0xaa, 0xfc, 0x3c, 0x81, 0x95, 0x67, 0x56, 0x29, 0x9f, 0x86, 0x1c,
|
|
||||||
0xbe, 0x8e, 0x12, 0x12, 0x5a, 0x61, 0x63, 0x50, 0xa9, 0xc0, 0x9e, 0xb7, 0x45, 0x52, 0x40, 0xc9,
|
|
||||||
0x68, 0xd2, 0x17, 0x20, 0x89, 0x91, 0x97, 0x5e, 0x04, 0x0b, 0xfb, 0x34, 0xc5, 0xfe, 0x4f, 0x5a,
|
|
||||||
0xc8, 0x6b, 0x70, 0xf1, 0x3d, 0x63, 0x6a, 0x17, 0x2c, 0xb9, 0xdf, 0x44, 0x4b, 0x72, 0xbb, 0x76,
|
|
||||||
0xf4, 0x2d, 0x00, 0xff, 0xfc, 0xed, 0x06, 0x75, 0xca, 0x81, 0x43, 0x32, 0x62, 0xe2, 0x00, 0x02,
|
|
||||||
0x53, 0x44, 0x59, 0x9c, 0x03, 0x60, 0xc6, 0xf3, 0x38, 0xdd, 0xc3, 0xee, 0xcf, 0x1d, 0x74, 0xda,
|
|
||||||
0x20, 0x64, 0xe0, 0x8c, 0xd6, 0xea, 0x99, 0xcd, 0xf3, 0xf8, 0x11, 0x31, 0x0e, 0xbe, 0x0b, 0xc6,
|
|
||||||
0x1e, 0x80, 0xb1, 0x98, 0x71, 0x71, 0x50, 0x2b, 0xac, 0x1c, 0xc7, 0x26, 0x3d, 0x05, 0xd1, 0xac,
|
|
||||||
0xec, 0x52, 0xb1, 0x9b, 0x70, 0xa0, 0xc1, 0xf3, 0x53, 0x07, 0x9d, 0xcd, 0x69, 0x1a, 0x41, 0xf4,
|
|
||||||
0xa3, 0xae, 0xf0, 0x6a, 0xbb, 0x25, 0x8f, 0x98, 0x81, 0xd5, 0x7d, 0x71, 0x76, 0xcf, 0xac, 0x1a,
|
|
||||||
0x1d, 0x39, 0xfd, 0x3e, 0x98, 0xe5, 0xf0, 0x21, 0x21, 0xe9, 0x5e, 0x01, 0x34, 0x5e, 0xf7, 0xc2,
|
|
||||||
0x6c, 0x38, 0x4a, 0x28, 0x98, 0x97, 0xc1, 0xb7, 0x41, 0xb4, 0xb8, 0xc4, 0x89, 0xd6, 0xbd, 0xb8,
|
|
||||||
0x2f, 0x62, 0xa0, 0x85, 0xbc, 0x43, 0xc2, 0x3c, 0x36, 0xa2, 0xa1, 0x4c, 0x00, 0xec, 0x7f, 0xb0,
|
|
||||||
0x88, 0x9e, 0x6c, 0x70, 0xc3, 0xeb, 0x8c, 0xe6, 0x3b, 0x9c, 0xf0, 0x82, 0xb9, 0xd7, 0xd0, 0xb2,
|
|
||||||
0xcc, 0x90, 0x38, 0x92, 0x61, 0x38, 0x15, 0x78, 0x80, 0xf1, 0xbc, 0xa0, 0x90, 0x56, 0x13, 0x7a,
|
|
||||||
0x05, 0xec, 0xbe, 0x0c, 0x6a, 0xd5, 0x36, 0xec, 0xfe, 0x01, 0x68, 0xc7, 0x40, 0xda, 0xd0, 0xee,
|
|
||||||
0x7d, 0x41, 0xbb, 0x77, 0x25, 0xed, 0xec, 0x56, 0x58, 0x05, 0xaa, 0xe4, 0x94, 0x44, 0x47, 0x22,
|
|
||||||
0x17, 0xb8, 0x5e, 0x13, 0xbc, 0x57, 0x1f, 0xc1, 0xc1, 0x40, 0xb3, 0x23, 0xd8, 0x74, 0x48, 0x62,
|
|
||||||
0x0e, 0x5e, 0x13, 0xdb, 0x84, 0x0a, 0x91, 0xef, 0x62, 0x9b, 0xf9, 0x9c, 0x09, 0xdf, 0x7b, 0x24,
|
|
||||||
0x94, 0x7c, 0xe8, 0xe7, 0xd9, 0xd0, 0x2a, 0xc3, 0xd6, 0x43, 0xd1, 0xba, 0xa2, 0xaa, 0x16, 0xcd,
|
|
||||||
0x0e, 0x60, 0xd1, 0xfd, 0x31, 0xc0, 0x04, 0x3f, 0x25, 0x54, 0x3a, 0xff, 0xcc, 0xe6, 0x45, 0x7c,
|
|
||||||
0x1c, 0x23, 0x83, 0xfb, 0x70, 0x90, 0xed, 0x5d, 0x21, 0x63, 0xd8, 0xcf, 0xa0, 0xa6, 0x28, 0x22,
|
|
||||||
0x7a, 0x51, 0xcc, 0x04, 0x62, 0xc5, 0x41, 0xb0, 0xa2, 0xce, 0x23, 0xc3, 0x17, 0xe7, 0x96, 0x49,
|
|
||||||
0x02, 0xe8, 0x81, 0x95, 0x63, 0xd8, 0xfd, 0x95, 0x83, 0x96, 0x75, 0x65, 0x6a, 0x2f, 0xce, 0x0a,
|
|
||||||
0xe4, 0x7b, 0x00, 0xe4, 0x3b, 0x3b, 0x45, 0x8f, 0xcf, 0x83, 0x45, 0xfe, 0x53, 0xd6, 0x93, 0x47,
|
|
||||||
0x80, 0xf2, 0xdf, 0x5b, 0x42, 0xab, 0x0d, 0x20, 0xb6, 0x20, 0x36, 0x9c, 0xee, 0xa8, 0x6d, 0xdd,
|
|
||||||
0xfb, 0x8a, 0x93, 0xee, 0x0d, 0xb4, 0x44, 0x46, 0x23, 0x4d, 0x90, 0xb3, 0xc1, 0x2a, 0x60, 0xfb,
|
|
||||||
0x92, 0x88, 0x94, 0xfc, 0x28, 0x20, 0x84, 0x52, 0xac, 0x86, 0xb1, 0x9f, 0x41, 0x04, 0xde, 0x41,
|
|
||||||
0xcb, 0x61, 0x96, 0x4a, 0xfe, 0x0b, 0xa6, 0x2c, 0x06, 0x29, 0x88, 0xbe, 0x29, 0xcc, 0x6e, 0x58,
|
|
||||||
0x8e, 0x7a, 0x7a, 0x87, 0xae, 0x58, 0x36, 0x8c, 0x21, 0x04, 0x1d, 0x0e, 0x24, 0xf5, 0x13, 0xc6,
|
|
||||||
0xb2, 0x30, 0x1e, 0x37, 0x21, 0xb3, 0x82, 0x65, 0xa2, 0x24, 0xf7, 0xde, 0xa4, 0x21, 0x17, 0x4c,
|
|
||||||
0x51, 0xc7, 0xee, 0x91, 0x10, 0xca, 0x06, 0x30, 0xf5, 0x47, 0xf3, 0x53, 0xe0, 0x35, 0x80, 0xf8,
|
|
||||||
0x2d, 0x71, 0xba, 0x69, 0xae, 0x87, 0x9a, 0xa7, 0xbd, 0x4f, 0x6d, 0xf5, 0xa6, 0x24, 0x1c, 0x18,
|
|
||||||
0xee, 0x1b, 0x9f, 0x97, 0x0c, 0x20, 0x68, 0x49, 0xac, 0x31, 0x08, 0xbf, 0x28, 0x4c, 0x17, 0xf0,
|
|
||||||
0x23, 0x33, 0x32, 0xd8, 0x04, 0x04, 0x58, 0x20, 0x88, 0x53, 0xc8, 0x00, 0x92, 0xa8, 0x6c, 0x92,
|
|
||||||
0x61, 0x84, 0xbe, 0x20, 0x35, 0x99, 0xaa, 0xa1, 0x6d, 0x60, 0xf7, 0x13, 0xa7, 0x4c, 0xe3, 0x25,
|
|
||||||
0x99, 0xc6, 0x7f, 0x16, 0x49, 0xf9, 0x27, 0x67, 0xf5, 0x95, 0x91, 0x30, 0x40, 0x92, 0x35, 0x93,
|
|
||||||
0xbf, 0xe2, 0x0c, 0x43, 0xb2, 0x4f, 0xab, 0x65, 0x47, 0xb8, 0xae, 0x47, 0x07, 0x04, 0x4a, 0x3a,
|
|
||||||
0x98, 0x81, 0x44, 0x84, 0xa2, 0x62, 0x23, 0xb4, 0x5e, 0x66, 0xef, 0xb0, 0x80, 0xbd, 0x3d, 0x3a,
|
|
||||||
0x66, 0x1e, 0xf2, 0x33, 0xaa, 0x60, 0xeb, 0x51, 0x91, 0xb6, 0x24, 0x8a, 0x54, 0xf0, 0xaa, 0x1b,
|
|
||||||
0x8d, 0x7c, 0x3f, 0x87, 0x76, 0x1c, 0xb1, 0xb2, 0xab, 0xc9, 0x74, 0xf6, 0x63, 0xb4, 0x36, 0x03,
|
|
||||||
0x29, 0xd9, 0x08, 0xbe, 0x52, 0xf7, 0xeb, 0xe8, 0xb4, 0x56, 0xab, 0x99, 0xb9, 0x18, 0xac, 0xc1,
|
|
||||||
0x91, 0x2f, 0xed, 0x96, 0xf6, 0xe0, 0xb0, 0x3a, 0x7e, 0x8a, 0xa1, 0x91, 0x75, 0x98, 0xff, 0xee,
|
|
||||||
0x42, 0x63, 0x02, 0xdc, 0xa1, 0xa2, 0x9c, 0x8c, 0x27, 0xc0, 0xd5, 0x49, 0x53, 0xe7, 0xc1, 0x54,
|
|
||||||
0xbb, 0x6e, 0x4a, 0xa4, 0xa5, 0x14, 0xc7, 0xee, 0x75, 0x93, 0x31, 0x0b, 0x32, 0x63, 0x2e, 0xc3,
|
|
||||||
0xe6, 0xa7, 0xcb, 0x8c, 0x69, 0x48, 0x67, 0x2d, 0xf7, 0x76, 0x19, 0xc5, 0x96, 0x8c, 0x62, 0x0c,
|
|
||||||
0x92, 0xf4, 0x7f, 0x11, 0x43, 0xec, 0x5f, 0x69, 0x74, 0xfe, 0xb8, 0x43, 0x94, 0xf3, 0xfd, 0xbf,
|
|
||||||
0x34, 0xd7, 0x8f, 0xd7, 0x47, 0x11, 0xf9, 0x2f, 0xdc, 0x57, 0x48, 0xf1, 0xf9, 0xdd, 0x67, 0xe4,
|
|
||||||
0x7e, 0x39, 0x7f, 0xba, 0xcb, 0x42, 0x5b, 0x71, 0xb0, 0x1c, 0xf3, 0xe8, 0x61, 0x63, 0xf6, 0x43,
|
|
||||||
0xaf, 0x7a, 0xb9, 0xef, 0xc1, 0x2c, 0x3a, 0xee, 0x57, 0xb5, 0x59, 0x8e, 0x6d, 0x62, 0x15, 0x9c,
|
|
||||||
0x1b, 0x0e, 0xa0, 0x21, 0x43, 0x03, 0x76, 0xff, 0xe1, 0xcc, 0x97, 0xfc, 0x1f, 0x8a, 0xb4, 0xfd,
|
|
||||||
0x6d, 0x35, 0x6d, 0xcb, 0x21, 0x45, 0xa5, 0xd7, 0xe1, 0x20, 0x63, 0x54, 0xd7, 0x04, 0x33, 0x29,
|
|
||||||
0x2a, 0x07, 0x48, 0x1f, 0xe6, 0xb4, 0x9f, 0x88, 0x62, 0x58, 0x8e, 0x6e, 0xba, 0x19, 0xbf, 0xdc,
|
|
||||||
0xb7, 0x1c, 0x60, 0x1e, 0x81, 0xb1, 0x54, 0x40, 0x25, 0x89, 0xea, 0xc6, 0x75, 0x32, 0xc8, 0x53,
|
|
||||||
0x1d, 0x59, 0xed, 0x36, 0x95, 0x63, 0x5e, 0xaf, 0x34, 0xa7, 0xfe, 0x6f, 0x2b, 0x4d, 0x33, 0xd9,
|
|
||||||
0xc7, 0xe9, 0xab, 0xc9, 0xfe, 0xfb, 0x45, 0xb4, 0xde, 0xb0, 0xfb, 0xa5, 0xb4, 0x18, 0xd2, 0xbc,
|
|
||||||
0x14, 0x60, 0x96, 0xf0, 0x3f, 0xa8, 0x37, 0x4c, 0x35, 0xf5, 0x8d, 0x93, 0xdd, 0x38, 0x24, 0xa2,
|
|
||||||
0x9c, 0xc4, 0x09, 0x93, 0x1d, 0xd3, 0x33, 0x3e, 0xc4, 0x0d, 0x4c, 0x13, 0xe7, 0xe6, 0x95, 0x19,
|
|
||||||
0x4b, 0x5b, 0xb5, 0x61, 0xca, 0x29, 0x2f, 0xf2, 0x54, 0x90, 0xee, 0x17, 0x0e, 0x7a, 0x22, 0x4e,
|
|
||||||
0xc3, 0x04, 0x6e, 0x0e, 0x5d, 0x90, 0xea, 0x0a, 0x89, 0xae, 0xb9, 0x1d, 0xc9, 0xdc, 0x58, 0x09,
|
|
||||||
0xf6, 0x01, 0xd4, 0x5e, 0x25, 0x66, 0x41, 0x96, 0x25, 0x14, 0x7a, 0x2e, 0xc0, 0xa1, 0xf9, 0x10,
|
|
||||||
0x5a, 0x0f, 0x78, 0x16, 0xae, 0x2f, 0x60, 0x30, 0x97, 0x56, 0xb5, 0xb8, 0x80, 0x59, 0x89, 0x00,
|
|
||||||
0x1b, 0x64, 0x45, 0x12, 0xa9, 0x40, 0x49, 0x7b, 0x11, 0xf6, 0xee, 0xd0, 0x3e, 0x29, 0x12, 0x2e,
|
|
||||||
0x67, 0xe8, 0x3e, 0x49, 0xe0, 0x0a, 0xe6, 0xfe, 0xae, 0x0a, 0xa8, 0xe0, 0x83, 0x1a, 0x22, 0x39,
|
|
||||||
0x15, 0xad, 0x04, 0x6f, 0x01, 0x20, 0x7e, 0x42, 0x40, 0xe2, 0xb7, 0xd0, 0x0b, 0x77, 0x3c, 0x11,
|
|
||||||
0x1e, 0xa0, 0x83, 0x24, 0xd1, 0x8c, 0xe8, 0x02, 0xb4, 0x62, 0xe6, 0x67, 0xd9, 0x3c, 0x4f, 0x07,
|
|
||||||
0x5f, 0x06, 0x2c, 0xeb, 0x15, 0x2c, 0xf7, 0xcc, 0x78, 0x0d, 0x42, 0x66, 0xda, 0xaf, 0x5c, 0xd9,
|
|
||||||
0xa0, 0x7a, 0x7e, 0xb2, 0x88, 0x3a, 0x0d, 0x1c, 0xd1, 0xd4, 0x80, 0x8a, 0x36, 0x51, 0x02, 0x9f,
|
|
||||||
0x06, 0x1b, 0x4f, 0xd5, 0x59, 0xa1, 0x8e, 0x12, 0xb3, 0xb2, 0xaf, 0x6f, 0x54, 0x2b, 0xe1, 0x62,
|
|
||||||
0x70, 0x01, 0x64, 0x3a, 0x65, 0x25, 0x34, 0x47, 0xb7, 0xdb, 0x2b, 0x03, 0x57, 0xeb, 0x33, 0x19,
|
|
||||||
0xb8, 0x1e, 0x98, 0x02, 0x3c, 0xf3, 0xa4, 0xfb, 0x0c, 0x20, 0xf4, 0xc5, 0x91, 0xc2, 0x22, 0x87,
|
|
||||||
0x4b, 0x11, 0xd7, 0xc5, 0x74, 0xe2, 0x68, 0x5f, 0x43, 0x9f, 0xe3, 0xf1, 0x90, 0x76, 0x75, 0x27,
|
|
||||||
0x97, 0x81, 0x3a, 0x1b, 0x5c, 0x02, 0xe9, 0x8b, 0x6a, 0x5a, 0x1b, 0x8e, 0x81, 0x85, 0x8b, 0x90,
|
|
||||||
0xde, 0x8b, 0xdd, 0x6f, 0x68, 0x61, 0x5d, 0x27, 0x65, 0xe1, 0x3a, 0x1b, 0x3c, 0x0b, 0xc2, 0xcf,
|
|
||||||
0x08, 0xe1, 0x84, 0x30, 0xde, 0xac, 0x41, 0x0b, 0x60, 0x37, 0x42, 0x67, 0x24, 0x67, 0x99, 0x2c,
|
|
||||||
0xd3, 0xed, 0xe5, 0x99, 0x8a, 0xf9, 0x55, 0x30, 0x70, 0x45, 0x86, 0x58, 0xfe, 0x36, 0x23, 0x5c,
|
|
||||||
0x59, 0x86, 0xc7, 0x7b, 0xf0, 0x43, 0x07, 0x6d, 0xcc, 0x58, 0x69, 0xf4, 0x14, 0xf4, 0x1a, 0x5a,
|
|
||||||
0x31, 0x85, 0x00, 0x78, 0x25, 0x40, 0x9d, 0xc3, 0xd3, 0x79, 0x18, 0xf8, 0x80, 0xe8, 0x42, 0xd9,
|
|
||||||
0x51, 0x1a, 0xca, 0x09, 0xf6, 0x3f, 0x6d, 0x35, 0x96, 0xbb, 0xbb, 0x94, 0x6b, 0x2d, 0x77, 0x54,
|
|
||||||
0xc5, 0xb2, 0xe5, 0xee, 0xd5, 0x09, 0x0c, 0x2f, 0xe2, 0x79, 0x14, 0xe0, 0xfb, 0xe6, 0xf2, 0x6b,
|
|
||||||
0xd2, 0x05, 0xd7, 0x07, 0x80, 0xa7, 0x00, 0xf5, 0xb9, 0xa9, 0xb4, 0x87, 0x09, 0xfb, 0x46, 0x25,
|
|
||||||
0x83, 0xd5, 0x4d, 0x5b, 0x12, 0xe3, 0xd8, 0xb4, 0xed, 0xfc, 0xdb, 0x41, 0x9f, 0x9f, 0xb0, 0x7e,
|
|
||||||
0x73, 0x32, 0x59, 0x2d, 0xcf, 0x6a, 0x25, 0x7c, 0x8f, 0xd6, 0xcb, 0xf7, 0x31, 0x75, 0xae, 0xf5,
|
|
||||||
0xd9, 0xd6, 0x39, 0xff, 0x9d, 0x46, 0x72, 0x35, 0x85, 0x45, 0x93, 0x6b, 0x7b, 0x3e, 0x72, 0xd9,
|
|
||||||
0x30, 0x19, 0x9f, 0x8c, 0x8d, 0x4f, 0xfe, 0x1f, 0x1d, 0xd4, 0x1e, 0x17, 0xdf, 0xa1, 0x5c, 0x5c,
|
|
||||||
0xf3, 0xd9, 0xc9, 0x6f, 0x99, 0x3b, 0xe8, 0x71, 0xc8, 0xaa, 0xec, 0xb0, 0x5b, 0x7b, 0x25, 0x94,
|
|
||||||
0xd4, 0x59, 0x09, 0xae, 0x83, 0x9a, 0xcd, 0x6f, 0x57, 0xdc, 0x29, 0x1d, 0x26, 0xf7, 0x33, 0xaf,
|
|
||||||
0x2a, 0x50, 0x16, 0x5f, 0x30, 0x88, 0xfd, 0x03, 0xf4, 0xfc, 0xd4, 0x01, 0xa1, 0x09, 0xbe, 0x4d,
|
|
||||||
0x86, 0x17, 0x50, 0x47, 0x94, 0xd3, 0x1a, 0x98, 0x2e, 0xd3, 0xbb, 0xb4, 0x17, 0x9f, 0xc0, 0xd3,
|
|
||||||
0xbc, 0xe0, 0xdf, 0x44, 0xd7, 0xe7, 0xb5, 0xab, 0xa7, 0x94, 0xbf, 0x3b, 0xe8, 0x66, 0x83, 0xe8,
|
|
||||||
0x2b, 0x69, 0xed, 0xb7, 0x25, 0x7b, 0xb7, 0xfa, 0x19, 0x22, 0x3d, 0xf6, 0x0a, 0xf4, 0x02, 0xf8,
|
|
||||||
0xed, 0x96, 0x99, 0xe3, 0x2a, 0x95, 0x42, 0x8c, 0x9f, 0x35, 0xbf, 0xc1, 0xfc, 0x21, 0xde, 0x38,
|
|
||||||
0xcb, 0xf7, 0x2b, 0x19, 0x93, 0xaf, 0xd6, 0x13, 0xf8, 0x0a, 0x68, 0xbb, 0x5c, 0x09, 0xa6, 0x78,
|
|
||||||
0xcf, 0x2b, 0x25, 0xea, 0xaf, 0xbb, 0xfe, 0x5f, 0x5b, 0xe8, 0xb9, 0xc6, 0x83, 0x94, 0x95, 0x75,
|
|
||||||
0x4b, 0x8d, 0xd7, 0xf5, 0x33, 0xbc, 0x38, 0x7e, 0x86, 0x0d, 0xb0, 0xba, 0x36, 0xe5, 0x0c, 0xcc,
|
|
||||||
0x16, 0x65, 0x3b, 0xaa, 0x3f, 0xa8, 0xa6, 0xbd, 0xea, 0xb7, 0x2f, 0x81, 0x86, 0xdb, 0x8d, 0x17,
|
|
||||||
0x4a, 0xdb, 0x24, 0xf4, 0x0b, 0x6f, 0xed, 0xe9, 0xab, 0x60, 0xaa, 0xfd, 0x18, 0xcd, 0xf7, 0x8c,
|
|
||||||
0x37, 0x5a, 0xd2, 0x1b, 0xd2, 0xb7, 0x53, 0xef, 0x33, 0xd3, 0x34, 0x5a, 0x6d, 0x6f, 0xa0, 0x53,
|
|
||||||
0xba, 0x0b, 0xa9, 0x26, 0x7b, 0x5c, 0x17, 0x92, 0x1d, 0xb6, 0x52, 0x70, 0xb6, 0xe1, 0x7a, 0x53,
|
|
||||||
0x36, 0x24, 0x3b, 0x13, 0xbb, 0x77, 0xd1, 0x72, 0x4e, 0x87, 0xd9, 0x81, 0x6e, 0xae, 0x3a, 0x77,
|
|
||||||
0x2a, 0x82, 0x42, 0xa7, 0x37, 0x20, 0x62, 0xee, 0x86, 0x6b, 0x85, 0xde, 0x5b, 0x3e, 0xc9, 0x99,
|
|
||||||
0x34, 0xdf, 0xfc, 0x68, 0x05, 0x3d, 0x36, 0x81, 0x48, 0xbc, 0xd1, 0x3e, 0x26, 0x34, 0xd4, 0xae,
|
|
||||||
0xf3, 0xee, 0x1a, 0x9e, 0xf5, 0x19, 0xaa, 0xf3, 0x2c, 0x9e, 0xf9, 0x71, 0xc0, 0xbf, 0x08, 0xd0,
|
|
||||||
0x9f, 0x54, 0x6b, 0x4c, 0x3e, 0x1f, 0xb2, 0xa3, 0x34, 0x54, 0x73, 0x8e, 0x86, 0x69, 0xf1, 0xd4,
|
|
||||||
0x6e, 0xb8, 0xcd, 0x78, 0x1a, 0x5f, 0x05, 0x9a, 0xf1, 0x4c, 0xb9, 0x2f, 0x4b, 0x3c, 0x6a, 0xed,
|
|
||||||
0x38, 0x3c, 0xb5, 0x4b, 0x48, 0x33, 0x9e, 0xc6, 0x6b, 0x76, 0x33, 0x9e, 0x29, 0x57, 0x1a, 0x89,
|
|
||||||
0x47, 0xad, 0x4d, 0xc3, 0xf3, 0x3e, 0xe0, 0x99, 0x18, 0x3c, 0xdc, 0x0d, 0x3c, 0xcf, 0x4d, 0xa8,
|
|
||||||
0x83, 0xf1, 0x5c, 0xe3, 0x8c, 0x2f, 0x1f, 0x9f, 0xed, 0x3a, 0x40, 0x1b, 0x1f, 0x4f, 0xdc, 0x0f,
|
|
||||||
0x01, 0xd6, 0x44, 0xcb, 0x6a, 0x86, 0x35, 0x75, 0xe0, 0x68, 0x86, 0x35, 0xbd, 0x11, 0xfa, 0x72,
|
|
||||||
0x52, 0x84, 0x75, 0xfd, 0xc7, 0x07, 0xdb, 0xf1, 0x01, 0x9f, 0x7d, 0x25, 0x37, 0x7e, 0xfb, 0xd4,
|
|
||||||
0x41, 0x9d, 0xe9, 0xf5, 0xda, 0xbd, 0x8e, 0x4f, 0xd4, 0x57, 0x3a, 0x37, 0xf0, 0x09, 0xfb, 0xc2,
|
|
||||||
0x5d, 0xc0, 0xbe, 0x65, 0x42, 0x6d, 0x06, 0x0b, 0x52, 0xeb, 0x83, 0x32, 0xee, 0xf5, 0xa2, 0x3e,
|
|
||||||
0x76, 0x38, 0xa8, 0x54, 0x9d, 0x57, 0x41, 0xd1, 0xbd, 0xdb, 0x70, 0xce, 0xfc, 0x20, 0x0e, 0xd5,
|
|
||||||
0x3c, 0xd2, 0x2f, 0xd2, 0x50, 0xed, 0xcf, 0x69, 0x62, 0x5e, 0x20, 0xe4, 0x90, 0x22, 0xf8, 0x94,
|
|
||||||
0x67, 0x69, 0x56, 0x34, 0x68, 0x97, 0x2a, 0xa0, 0xe2, 0x6c, 0xfe, 0x73, 0x01, 0x7d, 0x71, 0xe2,
|
|
||||||
0x50, 0x5b, 0xf2, 0x4f, 0x75, 0xee, 0x07, 0x30, 0x2b, 0x4c, 0xeb, 0x5d, 0xee, 0x2d, 0x7c, 0xd2,
|
|
||||||
0x4e, 0xd7, 0x39, 0x83, 0xb7, 0x33, 0xeb, 0x9b, 0x6b, 0x70, 0xa4, 0x0d, 0xbd, 0x91, 0xa9, 0xb6,
|
|
||||||
0x64, 0x9b, 0x44, 0x36, 0x12, 0x23, 0x22, 0x1f, 0xeb, 0x76, 0x22, 0x4d, 0x1f, 0x6f, 0x68, 0x45,
|
|
||||||
0xee, 0x57, 0xf0, 0x09, 0x7a, 0x56, 0x1d, 0xcd, 0x73, 0x80, 0xe6, 0x6a, 0x75, 0xb9, 0x8e, 0xa8,
|
|
||||||
0x6c, 0x05, 0x83, 0xb2, 0xb9, 0x74, 0xc4, 0x4b, 0xda, 0x17, 0x94, 0xcf, 0xea, 0x48, 0xff, 0xf6,
|
|
||||||
0x71, 0x7b, 0x21, 0x68, 0xfd, 0xd0, 0x71, 0xfe, 0x13, 0x00, 0x00, 0xff, 0xff, 0x0c, 0x81, 0x5e,
|
|
||||||
0xd6, 0x51, 0x1d, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user