add line webhook router

This commit is contained in:
Jay 2018-12-24 17:34:24 +08:00
parent 9d9fe262f4
commit 4726070ea5
19 changed files with 969 additions and 142 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
config.yml config.yml
*.swp
modules/schema/static.go

14
Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM golang:1.11-alpine3.8 as builder
WORKDIR /go/src/git.trj.tw/golang/mtgbot
RUN apk add --no-cache make git \
&& go get -u github.com/otakukaze/go-bindata/...
COPY . .
RUN make
FROM alpine:latest
RUN apk add --no-cache ca-certificates
WORKDIR /data
COPY --from=builder /go/src/git.trj.tw/golang/mtgbot/mtgbot /usr/bin
COPY config.sample.yml config.yml
EXPOSE 10230
CMD ["/usr/bin/mtgbot", "-f", "/data/config.yml", "-dbtool"]

9
Makefile Normal file
View File

@ -0,0 +1,9 @@
.PHONY: clean build
build:
go-bindata -pkg schema -ignore .git -o modules/schema/static.go schema/
GOOS=linux go build -o mtgbot -ldflags "-s -w" .
clean:
rm -rf mtgbot && go clean

View File

@ -1,4 +1,4 @@
port: 10231 port: 10230
line: line:
access: access:

43
go.mod
View File

@ -2,51 +2,24 @@ module git.trj.tw/golang/mtgbot
require ( require (
git.trj.tw/golang/utils v0.0.0-20181219032659-b1a8bce04189 git.trj.tw/golang/utils v0.0.0-20181219032659-b1a8bce04189
github.com/alecthomas/gometalinter v2.0.12+incompatible // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
github.com/cosiner/argv v0.0.1 // indirect
github.com/davidrjenni/reftools v0.0.0-20180914123528-654d0ba4f96d // indirect
github.com/derekparker/delve v1.1.0 // indirect
github.com/dustin/go-broadcast v0.0.0-20171205050544-f664265f5a66 // indirect
github.com/fatih/gomodifytags v0.0.0-20180914191908-141225bf62b6 // indirect
github.com/fatih/motion v0.0.0-20180408211639-218875ebe238 // indirect
github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 // indirect github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 // indirect
github.com/gin-gonic/autotls v0.0.0-20180426091246-be87bd5ef97b // indirect
github.com/gin-gonic/gin v1.3.0 github.com/gin-gonic/gin v1.3.0
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf // indirect github.com/golang/protobuf v1.2.0 // indirect
github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15 // indirect github.com/jmoiron/sqlx v1.2.0
github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4 // indirect
github.com/json-iterator/go v1.1.5 // indirect github.com/json-iterator/go v1.1.5 // indirect
github.com/jstemmer/gotags v1.4.1 // indirect github.com/lib/pq v1.0.0
github.com/kisielk/errcheck v1.1.0 // indirect
github.com/klauspost/asmfmt v1.2.0 // indirect
github.com/koron/iferr v0.0.0-20180615142939-bb332a3b1d91 // indirect
github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect github.com/mattn/go-isatty v0.0.4 // indirect
github.com/mdempsky/gocode v0.0.0-20181212191131-9c77a290fde2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/nicksnyder/go-i18n v1.10.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pelletier/go-toml v1.2.0 // indirect github.com/stretchr/testify v1.2.2 // indirect
github.com/peterh/liner v1.1.0 // indirect
github.com/rogpeppe/godef v1.1.1 // indirect
github.com/sirupsen/logrus v1.2.0 // indirect
github.com/spf13/cobra v0.0.3 // indirect
github.com/spf13/pflag v1.0.3 // indirect
github.com/stamblerre/gocode v0.0.0-20181212030458-2f9d39d8f31d // indirect
github.com/thinkerou/favicon v0.1.0 // indirect
github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 // indirect github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 // indirect
github.com/zmb3/gogetdoc v0.0.0-20181208215853-c5ca8f4d4936 // indirect
golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045 // indirect
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 // indirect
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1 // indirect
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 // indirect golang.org/x/net v0.0.0-20181220203305-927f97764cc3 // indirect
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 // indirect golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 // indirect
golang.org/x/tools v0.0.0-20181221235234-d00ac6d27372 // indirect google.golang.org/appengine v1.1.0 // indirect
google.golang.org/grpc v1.17.0 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 v2.2.2
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3 // indirect
) )

118
go.sum
View File

@ -1,136 +1,48 @@
9fans.net/go v0.0.0-20181112161441-237454027057 h1:OcHlKWkAMJEF1ndWLGxp5dnJQkYM/YImUOvsBoz6h5E=
9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
git.trj.tw/golang/utils v0.0.0-20181219032659-b1a8bce04189 h1:KHFlWRVFd5NIsnnFSy090+k6kT7KRotxUPTsho6F9lk= git.trj.tw/golang/utils v0.0.0-20181219032659-b1a8bce04189 h1:KHFlWRVFd5NIsnnFSy090+k6kT7KRotxUPTsho6F9lk=
git.trj.tw/golang/utils v0.0.0-20181219032659-b1a8bce04189/go.mod h1:yE+qbsUsijCTdwsaQRkPT1CXYk7ftMzXsCaaYx/0QI0= git.trj.tw/golang/utils v0.0.0-20181219032659-b1a8bce04189/go.mod h1:yE+qbsUsijCTdwsaQRkPT1CXYk7ftMzXsCaaYx/0QI0=
github.com/alecthomas/gometalinter v2.0.12+incompatible h1:RBUbc8pKtqRoVCymENDl7cpWS9Ht5XNnwwk0cKjpteI= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/alecthomas/gometalinter v2.0.12+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cosiner/argv v0.0.1 h1:2iAFN+sWPktbZ4tvxm33Ei8VY66FPCxdOxpncUGpAXE=
github.com/cosiner/argv v0.0.1/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidrjenni/reftools v0.0.0-20180914123528-654d0ba4f96d h1:aRvyac5PN1NEfcANJ1tfs8GMs5I9OXsVeg0FJkpXOys=
github.com/davidrjenni/reftools v0.0.0-20180914123528-654d0ba4f96d/go.mod h1:8o/GRMvsb9VyFbSEZGXfa0dkSXml4G23W0D/h9FksWM=
github.com/derekparker/delve v1.1.0 h1:icd65nMp7s2HiLz6y/6RCVXBdoED3xxYLwX09EMaRCc=
github.com/derekparker/delve v1.1.0/go.mod h1:pMSZMfp0Nhbm8qdZJkuE/yPGOkLpGXLS1I4poXQpuJU=
github.com/dustin/go-broadcast v0.0.0-20171205050544-f664265f5a66 h1:QnnoVdChKs+GeTvN4rPYTW6b5U6M3HMEvQ/+x4IGtfY=
github.com/dustin/go-broadcast v0.0.0-20171205050544-f664265f5a66/go.mod h1:kTEh6M2J/mh7nsskr28alwLCXm/DSG5OSA/o31yy2XU=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/gomodifytags v0.0.0-20180914191908-141225bf62b6 h1:iXJdM8Uob6EPOG/PFr5q0J124ysiZdJfACHqICBb3b8=
github.com/fatih/gomodifytags v0.0.0-20180914191908-141225bf62b6/go.mod h1:p2/x7bnOQsbq/deXsDIlj2yLiKFGPkD2nuoYqwn8R4Y=
github.com/fatih/motion v0.0.0-20180408211639-218875ebe238 h1:Qo4RxRMFag+fvDqQ6A3MblYBormptQUZ1ssOtV+EeQ8=
github.com/fatih/motion v0.0.0-20180408211639-218875ebe238/go.mod h1:pseIrV+t9A4+po+KJ1LheSnYH8m1qs6WhKx2zFiGi9I=
github.com/fatih/structtag v1.0.0 h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc=
github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA=
github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 h1:AzN37oI0cOS+cougNAV9szl6CVoj2RYwzS3DpUQNtlY= github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 h1:AzN37oI0cOS+cougNAV9szl6CVoj2RYwzS3DpUQNtlY=
github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-gonic/autotls v0.0.0-20180426091246-be87bd5ef97b h1:dm/NYytoj7p8Jc6zMvyRz3PCQrTTCXnVRvEzyBcM890=
github.com/gin-gonic/autotls v0.0.0-20180426091246-be87bd5ef97b/go.mod h1:vwfeXwKgEIWq63oVfwaBjoByS4dZzYbHHROHjV4IjNY=
github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs= github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs=
github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15 h1:cW/amwGEJK5MSKntPXRjX4dxs/nGxGT8gXKIsKFmHGc=
github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15/go.mod h1:Fdm/oWRW+CH8PRbLntksCNtmcCBximKPkVQYvmMl80k=
github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4 h1:gmIVMdGlVf5e6Yo6+ZklxdOrvtOvyrAjJyXAbmOznyo=
github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4/go.mod h1:t4Tr0tn92eq5ISef4cS5plFAMYAqZlAXtgUcKE6y8nw=
github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/gotags v1.4.1 h1:aWIyXsU3lTDqhsEC49MP85p2cUUWr2ptvdGNqqGA3r4= github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/jstemmer/gotags v1.4.1/go.mod h1:b6J3X0bsLbR4C5SgSx3V3KjuWTtmRzcmWPbTkWZ49PA= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/kisielk/errcheck v1.1.0 h1:ZqfnKyx9KGpRcW04j5nnPDgRgoXUeLh2YFBeFzphcA0=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/asmfmt v1.2.0 h1:zwsyBYgEdabg32alMful/5pRtMTcR5C5w1LKNg9OD78=
github.com/klauspost/asmfmt v1.2.0/go.mod h1:RAoUvqkWr2rUa2I19qKMEVZQe4BVtcHGTMCUOcCU2Lg=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/koron/iferr v0.0.0-20180615142939-bb332a3b1d91 h1:hunjgdb3b21ZdRmzDPXii0EcnHpjH7uCP+kODoE1JH0=
github.com/koron/iferr v0.0.0-20180615142939-bb332a3b1d91/go.mod h1:C2tFh8w3I6i4lnUJfoBx2Hwku3mgu4wPNTtUNp1i5KI=
github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227 h1:KIaAZ/V+/0/6BOULrmBQ9T1ed8BkKqGIjIKW923nJuo=
github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227/go.mod h1:ruMr5t05gVho4tuDv0PbI0Bb8nOxc/5Y6JzRHe/yfA0=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mdempsky/gocode v0.0.0-20181212191131-9c77a290fde2 h1:OqIVo8a2x2U2cn0+W044cmL3kSdCX5Rc7kRnK3ZRyAI=
github.com/mdempsky/gocode v0.0.0-20181212191131-9c77a290fde2/go.mod h1:hltEC42XzfMNgg0S1v6JTywwra2Mu6F6cLR03debVQ8=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.1.0 h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os=
github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/godef v1.1.1 h1:NujOtt9q9vIClRTB3sCZpavac+NMRaIayzrcz1h4fSE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/rogpeppe/godef v1.1.1/go.mod h1:oEo1eMy1VUEHUzUIX4F7IqvMJRiz9UId44mvnR8oPlQ=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stamblerre/gocode v0.0.0-20181212030458-2f9d39d8f31d h1:Bpu5DolLksGPpggDvoP5l9aruCElc6a47pHOSWwL74A=
github.com/stamblerre/gocode v0.0.0-20181212030458-2f9d39d8f31d/go.mod h1:EM2T8YDoTCvGXbEpFHxarbpv7VE26QD1++Cb1Pbh7Gs=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/thinkerou/favicon v0.1.0 h1:eWMISKTpHq2G8HOuKn7ydD55j5DDehx94b0C2y8ABMs=
github.com/thinkerou/favicon v0.1.0/go.mod h1:HL7Pap5kOluZv1ku34pZo/AJ44GaxMEPFZ3pmuexV2s=
github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 h1:EICbibRW4JNKMcY+LsWmuwob+CRS1BmdRdjphAm9mH4= github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 h1:EICbibRW4JNKMcY+LsWmuwob+CRS1BmdRdjphAm9mH4=
github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/zmb3/gogetdoc v0.0.0-20181208215853-c5ca8f4d4936 h1:+We2eeE8UuACEPcT7Ez1/yK0MN6SAqzy6S2JPxJTycQ=
github.com/zmb3/gogetdoc v0.0.0-20181208215853-c5ca8f4d4936/go.mod h1:ofmGw6LrMypycsiWcyug6516EXpIxSbZ+uI9ppGypfY=
golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045 h1:Pn8fQdvx+z1avAi7fdM2kRYWQNxGlavNDSyzrQg2SsU=
golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1 h1:rJm0LuqUjoDhSk2zO9ISMSToQxGz7Os2jRiOL8AWu4c=
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 h1:IcgEB62HYgAhX0Nd/QrVgZlxlcyxbGQHElLUhW2X4Fo= golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 h1:IcgEB62HYgAhX0Nd/QrVgZlxlcyxbGQHElLUhW2X4Fo=
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180824175216-6c1c5e93cdc1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181130195746-895048a75ecf/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181207195948-8634b1ecd393/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181221235234-d00ac6d27372 h1:zWPUEY/PjVHT+zO3L8OfkjrtIjf55joTxn/RQP/AjOI=
golang.org/x/tools v0.0.0-20181221235234-d00ac6d27372/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c h1:vTxShRUnK60yd8DZU+f95p1zSLj814+5CuEh7NjF2/Y=
gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3 h1:LyX67rVB0kBUFoROrQfzKwdrYLH1cRzHibxdJW85J1c=
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

12
main.go
View File

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"log" "log"
"git.trj.tw/golang/mtgbot/models"
"git.trj.tw/golang/mtgbot/modules/cmd"
"git.trj.tw/golang/mtgbot/modules/config" "git.trj.tw/golang/mtgbot/modules/config"
"git.trj.tw/golang/mtgbot/modules/options" "git.trj.tw/golang/mtgbot/modules/options"
"git.trj.tw/golang/mtgbot/router/routes" "git.trj.tw/golang/mtgbot/router/routes"
@ -24,6 +26,14 @@ func main() {
} }
conf := config.GetConf() conf := config.GetConf()
if opts.DBTool {
cmd.DBTool()
}
// init database connection
db := models.NewDB()
defer db.Close()
// register session object types // register session object types
regTypes() regTypes()
@ -34,4 +44,6 @@ func main() {
func regTypes() { func regTypes() {
gob.Register(map[string]interface{}{}) gob.Register(map[string]interface{}{})
gob.Register(models.Cards{})
gob.Register(models.Sets{})
} }

146
models/cards.go Normal file
View File

@ -0,0 +1,146 @@
package models
import (
"fmt"
"strings"
"github.com/jmoiron/sqlx"
)
// Cards -
type Cards struct {
ID string `db:"id" cc:"id"`
Name string `db:"name" cc:"name"`
CMC float32 `db:"cmc" cc:"cmc"`
ManaCost string `db:"mana_cost" cc:"mana_cost"`
Set string `db:"set" cc:"set"`
Text string `db:"text" cc:"text"`
Layout string `db:"layout" cc:"layout"`
ImageURL string `db:"image_url" cc:"image_url"`
Loyalty string `db:"loyalty" cc:"loyalty"`
Type string `db:"type" cc:"type"`
Number string `db:"number" cc:"number"`
Power string `db:"power" cc:"power"`
Toughness string `db:"toughness" cc:"toughness"`
Names []string `db:"names" cc:"names"`
Colors []string `db:"colors" cc:"colors"`
ColorIdentity []string `db:"color_identity" cc:"color_identity"`
Types []string `db:"types" cc:"types"`
Subtypes []string `db:"subtypes" cc:"subtypes"`
Supertypes []string `db:"supertypes" cc:"supertypes"`
}
// order opts
const (
CardSearchOrderByName OrderStr = `c."name" asc`
CardSearchOrderByNameDesc = `c."name" desc`
CardSearchOrderByCMC = `c."cmc" asc`
CardSearchOrderByCMCDesc = `c."cmc" desc"`
)
// CardSearchCMC -
type CardSearchCMC struct {
Op OpStr
Val float32
}
// ListCardsOpts -
type ListCardsOpts struct {
OrderBy OrderStr
Name string
CMC *CardSearchCMC
Set string
Types []string
Limit int
Offset int
}
// CountCards -
func CountCards(arg ListCardsOpts) (c int, err error) {
c = 0
query := `select count(*) as count from "public"."cards" c`
where := struct {
Name string `db:"name"`
CMC float32 `db:"name"`
Set string `db:"set"`
}{}
whereStr := []string{}
if len(arg.Name) > 0 {
where.Name = arg.Name
whereStr = append(whereStr, `c."name" = :name`)
}
if len(arg.Set) > 0 {
where.Set = arg.Set
whereStr = append(whereStr, `c."set" = :set`)
}
if arg.CMC != nil {
where.CMC = arg.CMC.Val
whereStr = append(whereStr, fmt.Sprintf(`c."cmc" %s :cmc`, arg.CMC.Op))
}
wStr := ""
if len(whereStr) > 0 {
wStr = fmt.Sprintf("where %s", strings.Join(whereStr, " and "))
}
query = fmt.Sprintf("%s %s",
query,
wStr)
q, a, err := sqlx.Named(query, where)
if err != nil {
return 0, err
}
err = x.Get(&c, q, a...)
return
}
// ListCards -
func ListCards(arg ListCardsOpts) (cards []*Cards, err error) {
if arg.Limit < 1 {
arg.Limit = 1
}
if arg.Offset < 0 {
arg.Offset = 0
}
query := `select c.id, c.name, c.cmc, c.mana_cost, c.text, c.layout, c.image_url, c.loyalty,
c.type, c.number, c.power, c.toughness, c.set from "public"."cards" c`
where := struct {
Name string `db:"name"`
CMC float32 `db:"cmc"`
Set string `db:"set"`
}{}
whereStr := []string{}
if len(arg.Name) > 0 {
where.Name = arg.Name
whereStr = append(whereStr, `c."name" = :name`)
}
if len(arg.Set) > 0 {
where.Set = arg.Set
whereStr = append(whereStr, `c."set" = :set`)
}
if arg.CMC != nil {
where.CMC = arg.CMC.Val
whereStr = append(whereStr, fmt.Sprintf(`c."cmc" %s :cmc`, arg.CMC.Op))
}
wStr := ""
if len(whereStr) > 0 {
wStr = fmt.Sprintf("where %s", strings.Join(whereStr, " and "))
}
query = fmt.Sprintf("%s %s %s %s",
query,
wStr,
arg.OrderBy,
fmt.Sprintf("limit %d offset %d", arg.Limit, arg.Offset))
q, a, err := sqlx.Named(query, where)
if err != nil {
return nil, err
}
err = x.Select(&cards, q, a...)
if err != nil {
return nil, err
}
return
}

72
models/models.go Normal file
View File

@ -0,0 +1,72 @@
package models
import (
"fmt"
"log"
"git.trj.tw/golang/mtgbot/modules/config"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
var x *sqlx.DB
// NewDB -
func NewDB() *sqlx.DB {
var err error
conf := config.GetConf()
userPassStr := conf.Database.User
if len(conf.Database.Pass) > 0 {
userPassStr += ":" + conf.Database.Pass
}
connStr := fmt.Sprintf("postgres://%s@%s/%s?sslmode=disable", userPassStr, conf.Database.Host, conf.Database.DB)
x, err = sqlx.Connect("postgres", connStr)
if err != nil {
log.Fatal(err)
}
x.SetMaxIdleConns(10)
x.SetMaxOpenConns(100)
err = x.Ping()
if err != nil {
log.Fatal(err)
}
return x
}
// String - get string ptr
func String(s string) *string {
return &s
}
// Int - get int ptr
func Int(i int) *int {
return &i
}
// OrderStr -
type OrderStr string
func (o OrderStr) String() string {
return string(o)
}
// OpStr -
type OpStr string
func (s OpStr) String() string {
return string(s)
}
// Op var
const (
SearchOpEq OpStr = "="
SearchOpNeq = "!="
SearchOpLt = "<"
SearchOpLte = "<="
SearchOpGt = ">"
SearchOpGte = ">="
)

114
models/sets.go Normal file
View File

@ -0,0 +1,114 @@
package models
import (
"fmt"
"strings"
"time"
"github.com/jmoiron/sqlx"
)
// Sets - product set
type Sets struct {
Code string `db:"code" cc:"code"`
Name string `db:"name" cc:"name"`
ReleaseDate time.Time `db:"release_date" cc:"release_date"`
}
// ListSetsOpts -
type ListSetsOpts struct {
OrderBy OrderStr
Code []string
Limit, Offset int
}
// order opts
const (
SetSearchOrderByName OrderStr = `s."name" asc`
SetSearchOrderByNameDesc = `s."name" desc`
)
// CountSets -
func CountSets(arg ListSetsOpts) (c int, err error) {
c = 0
query := `select count(*) as count from "public"."sets" s`
where := struct {
Code []string `db:"code"`
}{}
whereStr := []string{}
if len(arg.Code) > 0 {
where.Code = arg.Code
whereStr = append(whereStr, `s."code" in (:code)`)
}
wStr := ""
if len(whereStr) > 0 {
wStr = fmt.Sprintf(`where %s`, strings.Join(whereStr, " and "))
}
query = fmt.Sprintf("%s %s", query, wStr)
query, args, err := sqlx.Named(query, where)
if err != nil {
return 0, err
}
query, args, err = sqlx.In(query, args)
if err != nil {
return 0, err
}
query = x.Rebind(query)
err = x.Get(&c, query, args...)
return
}
// ListSets -
func ListSets(arg ListSetsOpts) (sets []*Sets, err error) {
if arg.Limit < 1 {
arg.Limit = 1
}
if arg.Offset < 0 {
arg.Offset = 0
}
query := `select s.code, s.name, s.release_date from "public"."sets" s`
where := struct {
Code []string `db:"code"`
}{}
whereStr := []string{}
if len(arg.Code) > 0 {
where.Code = arg.Code
whereStr = append(whereStr, `s."code" in (:code)`)
}
wStr := ""
if len(whereStr) > 0 {
wStr = fmt.Sprintf("where %s", strings.Join(whereStr, " and "))
}
query = fmt.Sprintf("%s %s %s %s",
query,
wStr,
arg.OrderBy,
fmt.Sprintf("limit %d offset %d", arg.Limit, arg.Offset))
query, args, err := sqlx.Named(query, where)
if err != nil {
return nil, err
}
query, args, err = sqlx.In(query, args)
if err != nil {
return nil, err
}
query = x.Rebind(query)
err = x.Select(&sets, query, args...)
if err != nil {
return nil, err
}
return
}

72
modules/apimsg/apimsg.go Normal file
View File

@ -0,0 +1,72 @@
package apimsg
// ResObject -
type ResObject struct {
Status int
Obj interface{}
}
var objs = map[string]*ResObject{
"Success": &ResObject{
Status: 200,
Obj: map[string]string{
"message": "success",
},
},
"InternalError": &ResObject{
Status: 500,
Obj: map[string]string{
"message": "internal error",
},
},
"NotFound": &ResObject{
Status: 400,
Obj: map[string]string{
"message": "not found",
},
},
"DataFormat": &ResObject{
Status: 400,
Obj: map[string]string{
"message": "data format error",
},
},
"LoginFirst": &ResObject{
Status: 401,
Obj: map[string]string{
"message": "login first",
},
},
"Forbidden": &ResObject{
Status: 403,
Obj: map[string]string{
"message": "forbidden",
},
},
}
// GetRes -
func GetRes(name string, msg interface{}) *ResObject {
obj, ok := objs[name]
if !ok {
obj = objs["InternalError"]
}
resobj := &ResObject{}
resobj.Status = obj.Status
switch msg.(type) {
case string:
tmp := make(map[string]string)
tmp["message"] = msg.(string)
resobj.Obj = tmp
break
case map[string]interface{}:
case map[string]string:
resobj.Obj = msg
break
default:
resobj.Obj = obj.Obj
}
return resobj
}

View File

@ -1 +1,84 @@
package cmd package cmd
import (
"database/sql"
"errors"
"log"
"git.trj.tw/golang/mtgbot/models"
"git.trj.tw/golang/mtgbot/modules/schema"
)
// DBTool - run db deploy
func DBTool() {
db := models.NewDB()
defer db.Close()
if db == nil {
log.Fatal(errors.New("database object is nil"))
}
dbver, err := schema.ReadVersions()
if err != nil {
log.Fatal(err)
}
version := -1
vcExists := false
// check version_ctrl table exists
row := db.QueryRowx(`select exists(select 1 from "information_schema"."tables" where "table_schema" = $1 and "table_name" = $2) as exists`, "public", "version_ctrl")
err = row.Scan(&vcExists)
if err != nil && err != sql.ErrNoRows {
log.Fatal(err)
}
if vcExists {
row := db.QueryRowx(`select max(version) as version from "public"."version_ctrl"`)
err := row.Scan(&version)
if err != nil && err != sql.ErrNoRows {
log.Fatal(err)
}
}
log.Println("Database Schema Version is ", version)
var vers []schema.VersionInfo
for _, v := range dbver.Versions {
if v.Version > version {
vers = append(vers, v)
}
}
if len(vers) == 0 {
return
}
tx, err := db.Beginx()
if err != nil {
log.Fatal(err)
}
for _, v := range vers {
log.Printf("Run Version: %d, FileName: %s\n", v.Version, v.File)
query, err := schema.ReadSchema(v.File)
if err != nil {
tx.Rollback()
log.Fatal(err)
}
// run schema file
_, err = tx.Exec(query)
if err != nil {
tx.Rollback()
log.Fatal(err)
}
// insert version data
_, err = tx.Exec(`insert into "public"."version_ctrl" ("version", "str") values ($1, $2)`, v.Version, query)
if err != nil {
tx.Rollback()
log.Fatal(err)
}
}
tx.Commit()
}

View File

@ -1,7 +1,10 @@
package context package context
import "github.com/gin-gonic/gin" import (
import "github.com/gin-gonic/gin/binding" "git.trj.tw/golang/mtgbot/modules/apimsg"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// Context - custom http context // Context - custom http context
type Context struct { type Context struct {
@ -31,3 +34,39 @@ func (c *Context) BindData(i interface{}) error {
func (c *Context) CustomRes(status int, msg interface{}) { func (c *Context) CustomRes(status int, msg interface{}) {
c.AbortWithStatusJSON(status, msg) c.AbortWithStatusJSON(status, msg)
} }
// LoginFirst -
func (c *Context) LoginFirst(msg interface{}) {
obj := apimsg.GetRes("LoginFirst", msg)
c.AbortWithStatusJSON(obj.Status, obj.Obj)
}
// NotFound -
func (c *Context) NotFound(msg interface{}) {
obj := apimsg.GetRes("NotFound", msg)
c.AbortWithStatusJSON(obj.Status, obj.Obj)
}
// DataFormat -
func (c *Context) DataFormat(msg interface{}) {
obj := apimsg.GetRes("DataFormat", msg)
c.AbortWithStatusJSON(obj.Status, obj.Obj)
}
// Forbidden -
func (c *Context) Forbidden(msg interface{}) {
obj := apimsg.GetRes("Forbidden", msg)
c.AbortWithStatusJSON(obj.Status, obj.Obj)
}
// Success -
func (c *Context) Success(msg interface{}) {
obj := apimsg.GetRes("Success", msg)
c.AbortWithStatusJSON(obj.Status, obj.Obj)
}
// ServerError -
func (c *Context) ServerError(msg interface{}) {
obj := apimsg.GetRes("InternalError", msg)
c.AbortWithStatusJSON(obj.Status, obj.Obj)
}

View File

@ -0,0 +1,70 @@
package lineobj
import (
"encoding/json"
"fmt"
)
// SourceObject -
type SourceObject struct {
Type string `json:"type" cc:"type"`
UserID string `json:"userId" cc:"userId"`
GroupID string `json:"groupId" cc:"groupId"`
}
// EventObject -
type EventObject struct {
Source *SourceObject `json:"source" cc:"source"`
Type string `json:"type" cc:"type"`
Timestamp int64 `json:"timestamp" cc:"timestamp"`
ReplyToken string `json:"replyToken" cc:"replyToken"`
Message map[string]interface{} `json:"message" cc:"message"`
}
// HookEvent -
type HookEvent struct {
Events []*EventObject `json:"events"`
}
// ParseWebhookBody -
func ParseWebhookBody(b []byte) *HookEvent {
if len(b) == 0 {
return nil
}
evt := &HookEvent{}
err := json.Unmarshal(b, evt)
if err != nil {
return nil
}
return evt
}
// MessageEvent -
func MessageEvent(e *EventObject) {
switch e.Type {
case "message":
// TODO
break
default:
fmt.Printf("line webhook type not match (%v)", e.Type)
}
}
func messageType(e *EventObject) {
msg := e.Message
mtype, ok := msg["type"]
if !ok {
return
}
if t, ok := mtype.(string); ok {
switch t {
case "text":
// TODO
break
case "iamge":
// TODO
break
}
}
}

44
modules/schema/schema.go Normal file
View File

@ -0,0 +1,44 @@
package schema
import (
"encoding/json"
"errors"
"fmt"
)
// DBVersion -
type DBVersion struct {
Versions []VersionInfo `json:"versions"`
Test []VersionInfo `json:"test"`
}
// VersionInfo -
type VersionInfo struct {
File string `json:"file"`
Version int `json:"version"`
}
// ReadVersions -
func ReadVersions() (dbver DBVersion, err error) {
f, err := Asset("schema/dbVersion.db")
if err != nil {
return dbver, err
}
err = json.Unmarshal(f, &dbver)
return
}
// ReadSchema -
func ReadSchema(name string) (q string, err error) {
if len(name) == 0 {
return "", errors.New("name is empty")
}
f, err := Asset(fmt.Sprintf("schema/%s", name))
if err != nil {
return "", err
}
q = string(f)
return
}

93
router/line/line.go Normal file
View File

@ -0,0 +1,93 @@
package line
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"io/ioutil"
"git.trj.tw/golang/mtgbot/modules/config"
"git.trj.tw/golang/mtgbot/modules/context"
"git.trj.tw/golang/mtgbot/modules/lineobj"
)
// GetRawBody -
func GetRawBody(c *context.Context) {
byteBody, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.DataFormat("body read fail")
return
}
c.Set("rawbody", byteBody)
c.Next()
}
// VerifyLine -
func VerifyLine(c *context.Context) {
rawbody, ok := c.Get("rawbody")
if !ok {
c.DataFormat("body read fail")
return
}
var raw []byte
if raw, ok = rawbody.([]byte); !ok {
c.DataFormat("body type error")
return
}
sign := c.GetHeader("X-Line-Signature")
if len(sign) == 0 {
c.Next()
return
}
conf := config.GetConf()
hash := hmac.New(sha256.New, []byte(conf.Line.Secret))
_, err := hash.Write(raw)
if err != nil {
c.ServerError(nil)
return
}
hashSign := base64.StdEncoding.EncodeToString(hash.Sum(nil))
if hashSign != sign {
c.CustomRes(403, map[string]string{
"message": "sign verify fail",
})
return
}
c.Next()
}
// LineWebhook -
func LineWebhook(c *context.Context) {
rawbody, ok := c.Get("rawbody")
if !ok {
c.DataFormat("body read fail")
return
}
var raw []byte
if raw, ok = rawbody.([]byte); !ok {
c.DataFormat("body type error")
return
}
events := lineobj.ParseWebhookBody(raw)
if events == nil {
c.ServerError(nil)
return
}
if len(events.Events) > 0 {
for _, v := range events.Events {
go lineobj.MessageEvent(v)
}
}
c.Success(nil)
}

View File

@ -1,6 +1,10 @@
package routes package routes
import "github.com/gin-gonic/gin" import (
"git.trj.tw/golang/mtgbot/modules/context"
"git.trj.tw/golang/mtgbot/router/line"
"github.com/gin-gonic/gin"
)
var r *gin.Engine var r *gin.Engine
@ -16,4 +20,8 @@ func SetRoutes(r *gin.Engine) {
r.GET("/", func(c *gin.Context) { r.GET("/", func(c *gin.Context) {
c.String(200, "Hello") c.String(200, "Hello")
}) })
r.POST("/line", context.PatchCtx(line.GetRawBody), context.PatchCtx(line.VerifyLine), context.PatchCtx(line.LineWebhook))
r.POST("/line/", context.PatchCtx(line.GetRawBody), context.PatchCtx(line.VerifyLine), context.PatchCtx(line.LineWebhook))
} }

6
schema/dbVersion.json Normal file
View File

@ -0,0 +1,6 @@
{
"versions": [
{"file": "main.sql", "version": 1}
],
"test": []
}

158
schema/main.sql Normal file
View File

@ -0,0 +1,158 @@
--
-- PostgreSQL database dump
--
-- Dumped from database version 10.6 (Debian 10.6-1.pgdg90+1)
-- Dumped by pg_dump version 10.6 (Debian 10.6-1.pgdg90+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
ALTER TABLE IF EXISTS ONLY public.sets DROP CONSTRAINT IF EXISTS sets_pk;
ALTER TABLE IF EXISTS ONLY public.cards DROP CONSTRAINT IF EXISTS cards_pk;
DROP TABLE IF EXISTS public.version_ctrl;
DROP TABLE IF EXISTS public.sets;
DROP TABLE IF EXISTS public.cards;
DROP EXTENSION IF EXISTS "uuid-ossp";
DROP EXTENSION IF EXISTS plpgsql;
DROP SCHEMA IF EXISTS public;
--
-- Name: public; Type: SCHEMA; Schema: -; Owner: -
--
CREATE SCHEMA public;
--
-- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON SCHEMA public IS 'standard public schema';
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
--
-- Name: uuid-ossp; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public;
--
-- Name: EXTENSION "uuid-ossp"; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UUIDs)';
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: cards; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.cards (
id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
name character varying(1024) DEFAULT ''::character varying NOT NULL,
cmc double precision DEFAULT 0 NOT NULL,
mana_cost character varying(64) DEFAULT ''::character varying NOT NULL,
text character varying(2048) DEFAULT ''::character varying NOT NULL,
layout character varying(32) DEFAULT ''::character varying NOT NULL,
image_url character varying(1024) DEFAULT ''::character varying NOT NULL,
loyalty character varying(32) DEFAULT ''::character varying NOT NULL,
type character varying(128) DEFAULT ''::character varying NOT NULL,
number character varying(32) DEFAULT ''::character varying NOT NULL,
power character varying(32) DEFAULT ''::character varying NOT NULL,
toughness character varying(32) DEFAULT ''::character varying NOT NULL,
set character varying(32) DEFAULT ''::character varying NOT NULL,
names text[] DEFAULT ARRAY[]::text[] NOT NULL,
colors text[] DEFAULT ARRAY[]::text[] NOT NULL,
color_identity text[] DEFAULT ARRAY[]::text[] NOT NULL,
types text[] DEFAULT ARRAY[]::text[] NOT NULL,
supertypes text[] DEFAULT ARRAY[]::text[] NOT NULL,
subtypes text[] DEFAULT ARRAY[]::text[] NOT NULL
);
--
-- Name: sets; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.sets (
code character varying(32) NOT NULL,
name character varying(128) NOT NULL,
release_date date
);
--
-- Name: version_ctrl; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.version_ctrl (
version integer DEFAULT 0 NOT NULL,
str character varying(4096) DEFAULT ''::character varying NOT NULL,
ctime timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Data for Name: cards; Type: TABLE DATA; Schema: public; Owner: -
--
--
-- Data for Name: sets; Type: TABLE DATA; Schema: public; Owner: -
--
--
-- Data for Name: version_ctrl; Type: TABLE DATA; Schema: public; Owner: -
--
--
-- Name: cards cards_pk; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.cards
ADD CONSTRAINT cards_pk PRIMARY KEY (id);
--
-- Name: sets sets_pk; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.sets
ADD CONSTRAINT sets_pk PRIMARY KEY (code);
--
-- PostgreSQL database dump complete
--