add line webhook router
This commit is contained in:
		
							parent
							
								
									9d9fe262f4
								
							
						
					
					
						commit
						4726070ea5
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1 +1,3 @@
 | 
			
		||||
config.yml
 | 
			
		||||
*.swp
 | 
			
		||||
modules/schema/static.go
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Dockerfile
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										9
									
								
								Makefile
									
									
									
									
									
										Normal 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
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
port: 10231
 | 
			
		||||
port: 10230
 | 
			
		||||
 | 
			
		||||
line:
 | 
			
		||||
  access:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										43
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								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
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										118
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								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=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										146
									
								
								models/cards.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								models/cards.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										72
									
								
								models/models.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										114
									
								
								models/sets.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										72
									
								
								modules/apimsg/apimsg.go
									
									
									
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
@ -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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										70
									
								
								modules/lineobj/lineobj.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								modules/lineobj/lineobj.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										44
									
								
								modules/schema/schema.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										93
									
								
								router/line/line.go
									
									
									
									
									
										Normal 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)
 | 
			
		||||
}
 | 
			
		||||
@ -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))
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								schema/dbVersion.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								schema/dbVersion.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "versions": [
 | 
			
		||||
    {"file": "main.sql", "version": 1}
 | 
			
		||||
  ],
 | 
			
		||||
  "test": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										158
									
								
								schema/main.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								schema/main.sql
									
									
									
									
									
										Normal 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
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user