diff --git a/.gitignore b/.gitignore index 1d3ed4c..b965239 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ config.yml +*.swp +modules/schema/static.go diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..45ac21e --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8f12eb9 --- /dev/null +++ b/Makefile @@ -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 diff --git a/config.sample.yml b/config.sample.yml index a13d772..412a73b 100644 --- a/config.sample.yml +++ b/config.sample.yml @@ -1,4 +1,4 @@ -port: 10231 +port: 10230 line: access: diff --git a/go.mod b/go.mod index 93fa9a3..0a386c2 100644 --- a/go.mod +++ b/go.mod @@ -2,51 +2,24 @@ module git.trj.tw/golang/mtgbot require ( git.trj.tw/golang/utils v0.0.0-20181219032659-b1a8bce04189 - github.com/alecthomas/gometalinter v2.0.12+incompatible // 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/davecgh/go-spew v1.1.1 // 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/google/shlex v0.0.0-20181106134648-c34317bd91bf // indirect - github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15 // indirect - github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4 // indirect + github.com/golang/protobuf v1.2.0 // indirect + github.com/jmoiron/sqlx v1.2.0 github.com/json-iterator/go v1.1.5 // indirect - github.com/jstemmer/gotags v1.4.1 // indirect - 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/lib/pq v1.0.0 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/reflect2 v1.0.1 // indirect - github.com/nicksnyder/go-i18n v1.10.0 // indirect - github.com/pelletier/go-toml v1.2.0 // 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/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.2.2 // 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/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 // indirect - golang.org/x/tools v0.0.0-20181221235234-d00ac6d27372 // indirect - google.golang.org/grpc v1.17.0 // indirect - gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect + google.golang.org/appengine v1.1.0 // indirect + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v8 v8.18.2 // indirect gopkg.in/yaml.v2 v2.2.2 - honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3 // indirect ) diff --git a/go.sum b/go.sum index 7d30b91..a87ed1c 100644 --- a/go.sum +++ b/go.sum @@ -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/go.mod h1:yE+qbsUsijCTdwsaQRkPT1CXYk7ftMzXsCaaYx/0QI0= -github.com/alecthomas/gometalinter v2.0.12+incompatible h1:RBUbc8pKtqRoVCymENDl7cpWS9Ht5XNnwwk0cKjpteI= -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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/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/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= +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/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= -github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= -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/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= 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/jstemmer/gotags v1.4.1 h1:aWIyXsU3lTDqhsEC49MP85p2cUUWr2ptvdGNqqGA3r4= -github.com/jstemmer/gotags v1.4.1/go.mod h1:b6J3X0bsLbR4C5SgSx3V3KjuWTtmRzcmWPbTkWZ49PA= -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/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 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-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -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/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 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/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 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/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/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 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 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/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/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/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/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -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 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= -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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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/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/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= diff --git a/main.go b/main.go index 0253c6f..45daad2 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,8 @@ import ( "fmt" "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/options" "git.trj.tw/golang/mtgbot/router/routes" @@ -24,6 +26,14 @@ func main() { } conf := config.GetConf() + if opts.DBTool { + cmd.DBTool() + } + + // init database connection + db := models.NewDB() + defer db.Close() + // register session object types regTypes() @@ -34,4 +44,6 @@ func main() { func regTypes() { gob.Register(map[string]interface{}{}) + gob.Register(models.Cards{}) + gob.Register(models.Sets{}) } diff --git a/models/cards.go b/models/cards.go new file mode 100644 index 0000000..3b7e1f1 --- /dev/null +++ b/models/cards.go @@ -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 +} diff --git a/models/models.go b/models/models.go new file mode 100644 index 0000000..cefecd9 --- /dev/null +++ b/models/models.go @@ -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 = ">=" +) diff --git a/models/sets.go b/models/sets.go new file mode 100644 index 0000000..6628800 --- /dev/null +++ b/models/sets.go @@ -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 +} diff --git a/modules/apimsg/apimsg.go b/modules/apimsg/apimsg.go new file mode 100644 index 0000000..b21eecc --- /dev/null +++ b/modules/apimsg/apimsg.go @@ -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 +} diff --git a/modules/cmd/cmd.go b/modules/cmd/cmd.go index 1d619dd..7341087 100644 --- a/modules/cmd/cmd.go +++ b/modules/cmd/cmd.go @@ -1 +1,84 @@ 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() +} diff --git a/modules/context/context.go b/modules/context/context.go index d848ffc..647ee73 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -1,7 +1,10 @@ package context -import "github.com/gin-gonic/gin" -import "github.com/gin-gonic/gin/binding" +import ( + "git.trj.tw/golang/mtgbot/modules/apimsg" + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" +) // Context - custom http context type Context struct { @@ -31,3 +34,39 @@ func (c *Context) BindData(i interface{}) error { func (c *Context) CustomRes(status int, msg interface{}) { 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) +} diff --git a/modules/lineobj/lineobj.go b/modules/lineobj/lineobj.go new file mode 100644 index 0000000..9f55e19 --- /dev/null +++ b/modules/lineobj/lineobj.go @@ -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 + } + } +} diff --git a/modules/schema/schema.go b/modules/schema/schema.go new file mode 100644 index 0000000..2917661 --- /dev/null +++ b/modules/schema/schema.go @@ -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 +} diff --git a/router/line/line.go b/router/line/line.go new file mode 100644 index 0000000..901923a --- /dev/null +++ b/router/line/line.go @@ -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) +} diff --git a/router/routes/routes.go b/router/routes/routes.go index 39259da..6f010f6 100644 --- a/router/routes/routes.go +++ b/router/routes/routes.go @@ -1,6 +1,10 @@ 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 @@ -16,4 +20,8 @@ func SetRoutes(r *gin.Engine) { r.GET("/", func(c *gin.Context) { 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)) + } diff --git a/schema/dbVersion.json b/schema/dbVersion.json new file mode 100644 index 0000000..6eee753 --- /dev/null +++ b/schema/dbVersion.json @@ -0,0 +1,6 @@ +{ + "versions": [ + {"file": "main.sql", "version": 1} + ], + "test": [] +} diff --git a/schema/main.sql b/schema/main.sql new file mode 100644 index 0000000..1a98673 --- /dev/null +++ b/schema/main.sql @@ -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 +-- +