Refactored code and added logging

This commit is contained in:
Artyom Belousov 2019-11-03 12:16:45 +03:00
parent 8830920900
commit 221ab214cc
11 changed files with 51 additions and 44 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@ vendor
go-mtg-vk go-mtg-vk
*.swp *.swp
hosts hosts
.idea

View file

@ -23,11 +23,11 @@ func GetClient() *CacheClient {
func (client *CacheClient) Init() { func (client *CacheClient) Init() {
client.storage = redis.NewClient(&redis.Options{ client.storage = redis.NewClient(&redis.Options{
Addr: HOST_NAME, Addr: HostName,
Password: PASSWORD, Password: Password,
DB: 0, DB: 0,
}) })
client.Expiration = CACHE_EXPIRATION client.Expiration = CacheExpiration
} }
func (client *CacheClient) Set(key string, value string) { func (client *CacheClient) Set(key string, value string) {

View file

@ -4,6 +4,6 @@ import (
"time" "time"
) )
const HOST_NAME = "redis:6379" const HostName = "redis:6379"
const PASSWORD = "" const Password = ""
const CACHE_EXPIRATION = time.Hour * 24 const CacheExpiration = time.Hour * 24

View file

@ -8,25 +8,25 @@ import (
"strings" "strings"
) )
const SCRYFALL_URL = "https://api.scryfall.com" const ScryfallUrl = "https://api.scryfall.com"
func GetNameByCardId(set string, number string) string { func GetNameByCardId(set string, number string) string {
/* /*
Note: number is string because some cards contain letters in their numbers. Note: number is string because some cards contain letters in their numbers.
*/ */
path := SCRYFALL_URL + "/cards/" + strings.ToLower(set) + "/" + number path := ScryfallUrl + "/cards/" + strings.ToLower(set) + "/" + number
return GetCardByUrl(path) return GetCardByUrl(path)
} }
func GetOriginalName(name string) string { func GetOriginalName(name string) string {
path := SCRYFALL_URL + "/cards/named?fuzzy=" + ApplyFilters(name) path := ScryfallUrl + "/cards/named?fuzzy=" + ApplyFilters(name)
return GetCardByUrl(path) return GetCardByUrl(path)
} }
func ApplyFilters(name string) string { func ApplyFilters(name string) string {
/* /*
Despite of the rules of Russian language, letter ё is replaced with e on cards Despite of the rules of Russian language, letter ё is replaced with e on cards
Sometimes it leads to wrong search results Sometimes it leads to wrong search results
*/ */
name = strings.ReplaceAll(name, "ё", "е") name = strings.ReplaceAll(name, "ё", "е")
return url.QueryEscape(name) return url.QueryEscape(name)
@ -43,6 +43,9 @@ func GetCardByUrl(path string) string {
return "" return ""
} }
var v Card var v Card
json.Unmarshal(data, &v) err = json.Unmarshal(data, &v)
if err != nil {
return ""
}
return v.getName() return v.getName()
} }

View file

@ -8,7 +8,7 @@ import (
"strings" "strings"
) )
const SCGURL = "http://www.starcitygames.com/results?name=" const Scgurl = "http://www.starcitygames.com/results?name="
func GetSCGPrices(name string) ([]CardPrice, error) { func GetSCGPrices(name string) ([]CardPrice, error) {
preprocessedName := preprocessNameForSearch(name) preprocessedName := preprocessNameForSearch(name)
@ -69,7 +69,7 @@ func getPriceContainers(doc *html.Node) []*html.Node {
func fetchPrice(price string) (float64, error) { func fetchPrice(price string) (float64, error) {
split := strings.Split(price, "$") split := strings.Split(price, "$")
if len(split) < 2 { if len(split) < 2 {
return 0, errors.New("Not enough values") return 0, errors.New("not enough values")
} }
p := split[1] p := split[1]
v, err := strconv.ParseFloat(p, 64) v, err := strconv.ParseFloat(p, 64)
@ -77,9 +77,9 @@ func fetchPrice(price string) (float64, error) {
} }
func getSCGUrl(name string) string { func getSCGUrl(name string) string {
splitted := strings.Split(name, " ") words := strings.Split(name, " ")
scgName := strings.Join(splitted, "+") scgName := strings.Join(words, "+")
url := SCGURL + scgName url := Scgurl + scgName
return url return url
} }

View file

@ -10,10 +10,10 @@ then
sudo docker rmi -f $TEST_IMAGE_NAME sudo docker rmi -f $TEST_IMAGE_NAME
sudo docker build -t $TEST_IMAGE_NAME . sudo docker build -t $TEST_IMAGE_NAME .
TEST_CONTAINER_NAME="go_mtg_vk_test_container" TEST_CONTAINER_NAME="go_mtg_vk_test_container"
sudo docker run --rm --name $TEST_CONTAINER_NAME --network $TEST_NETWORK_NAME -e MODE="test" -e VK_TOKEN=$VK_TOKEN -e VK_SECRET_KEY=$VK_SECRET_KEY -e VK_GROUP_ID=$VK_GROUP_ID -e VK_CONFIRMATION_STRING=$VK_CONFIRMATION_STRING $TEST_IMAGE_NAME sudo docker run --rm --name $TEST_CONTAINER_NAME --network $TEST_NETWORK_NAME -e MODE="test" -e VK_TOKEN="$VK_TOKEN" -e VK_SECRET_KEY="$VK_SECRET_KEY" -e VK_GROUP_ID="$VK_GROUP_ID" -e VK_CONFIRMATION_STRING="$VK_CONFIRMATION_STRING" $TEST_IMAGE_NAME
EXIT_CODE=$(sudo docker inspect $TEST_CONTAINER_NAME --format "{{.State.ExitCode}}") EXIT_CODE=$(sudo docker inspect $TEST_CONTAINER_NAME --format "{{.State.ExitCode}}")
sudo docker rm -f $TEST_REDIS_NAME sudo docker rm -f $TEST_REDIS_NAME
exit $EXIT_CODE exit "$EXIT_CODE"
elif [[ $1 = "prod" ]] elif [[ $1 = "prod" ]]
then then
PROD_NETWORK_NAME="go_mtg_vk_prod_network" PROD_NETWORK_NAME="go_mtg_vk_prod_network"
@ -26,5 +26,5 @@ then
PROD_CONTAINER_NAME="go_mtg_vk_prod_container" PROD_CONTAINER_NAME="go_mtg_vk_prod_container"
sudo docker stop $PROD_CONTAINER_NAME sudo docker stop $PROD_CONTAINER_NAME
sudo docker rm $PROD_CONTAINER_NAME sudo docker rm $PROD_CONTAINER_NAME
sudo docker run -v /var/log/go_mtg_vk:/go/src/go-mtg-vk/logs -d -p 80:80 --network $PROD_NETWORK_NAME --restart always --name $PROD_CONTAINER_NAME -e MODE="prod" -e VK_TOKEN=$VK_TOKEN -e VK_SECRET_KEY=$VK_SECRET_KEY -e VK_GROUP_ID=$VK_GROUP_ID -e VK_CONFIRMATION_STRING=$VK_CONFIRMATION_STRING $PROD_IMAGE_NAME sudo docker run -v /var/log/go_mtg_vk:/go/src/go-mtg-vk/logs -d -p 80:80 --network $PROD_NETWORK_NAME --restart always --name $PROD_CONTAINER_NAME -e MODE="prod" -e VK_TOKEN="$VK_TOKEN" -e VK_SECRET_KEY="$VK_SECRET_KEY" -e VK_GROUP_ID="$VK_GROUP_ID" -e VK_CONFIRMATION_STRING="$VK_CONFIRMATION_STRING" $PROD_IMAGE_NAME
fi fi

View file

@ -9,10 +9,10 @@ sudo docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock\ -v /var/run/docker.sock:/var/run/docker.sock\
-v jenkins_home_mtg_go:/var/jenkins_home\ -v jenkins_home_mtg_go:/var/jenkins_home\
--name $CONTAINER_NAME\ --name $CONTAINER_NAME\
-e VK_TOKEN=$VK_TOKEN\ -e VK_TOKEN="$VK_TOKEN"\
-e VK_SECRET_KEY=$VK_SECRET_KEY\ -e VK_SECRET_KEY="$VK_SECRET_KEY"\
-e VK_GROUP_ID=$VK_GROUP_ID\ -e VK_GROUP_ID="$VK_GROUP_ID"\
-e VK_CONFIRMATION_STRING=$VK_CONFIRMATION_STRING\ -e VK_CONFIRMATION_STRING="$VK_CONFIRMATION_STRING"\
--name $CONTAINER_NAME\ --name $CONTAINER_NAME\
$IMAGE_NAME $IMAGE_NAME
sudo docker exec -it $CONTAINER_NAME sudo service docker start sudo docker exec -it $CONTAINER_NAME sudo service docker start

View file

@ -13,10 +13,9 @@ import (
func main() { func main() {
rand.Seed(time.Now().UTC().UnixNano()) rand.Seed(time.Now().UTC().UnixNano())
logFile, _ := os.OpenFile("logs/errors.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) logFile, _ := os.OpenFile("logs/errors.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
defer logFile.Close()
log.SetOutput(logFile) log.SetOutput(logFile)
r := gin.Default() r := gin.Default()
r.POST("callback/message", vk.HandleMessage) r.POST("callback/message", vk.HandleMessage)
r.Run(":80") _ = r.Run(":80")
} }

View file

@ -12,7 +12,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
const CARDSLIMIT = 8 const Cardslimit = 8
func min(a, b int) int { func min(a, b int) int {
if a < b { if a < b {
@ -23,20 +23,20 @@ func min(a, b int) int {
func HandleMessage(c *gin.Context) { func HandleMessage(c *gin.Context) {
var req MessageRequest var req MessageRequest
c.BindJSON(&req) _ = c.BindJSON(&req)
if req.Secret != SECRET_KEY { if req.Secret != SecretKey {
return return
} }
switch req.Type { switch req.Type {
case "confirmation": case "confirmation":
handleConfirmation(c, &req) handleConfirmation(c, &req)
case "message_new": case "message_new":
go handleSearch(c, &req) go handleSearch(&req)
c.String(http.StatusOK, "ok") c.String(http.StatusOK, "ok")
} }
} }
func handleSearch(c *gin.Context, req *MessageRequest) { func handleSearch(req *MessageRequest) {
cardName, err := getCardNameByCommand(req.Object.Body) cardName, err := getCardNameByCommand(req.Object.Body)
if err != nil { if err != nil {
Message(req.Object.UserId, "Некорректная команда") Message(req.Object.UserId, "Некорректная команда")
@ -51,7 +51,7 @@ func handleSearch(c *gin.Context, req *MessageRequest) {
log.Printf("Could not find SCG prices\n error message: %s\n card name: %s", err.Error(), cardName) log.Printf("Could not find SCG prices\n error message: %s\n card name: %s", err.Error(), cardName)
return return
} }
elements := min(CARDSLIMIT, len(prices)) elements := min(Cardslimit, len(prices))
prices = prices[:elements] prices = prices[:elements]
priceInfo := cardsinfo.FormatCardPrices(cardName, prices) priceInfo := cardsinfo.FormatCardPrices(cardName, prices)
Message(req.Object.UserId, priceInfo) Message(req.Object.UserId, priceInfo)
@ -74,7 +74,7 @@ func GetPrices(cardName string) ([]cardsinfo.CardPrice, error) {
client.Set(cardName, string(serialized)) client.Set(cardName, string(serialized))
return prices, nil return prices, nil
} }
json.Unmarshal([]byte(val), &prices) _ = json.Unmarshal([]byte(val), &prices)
return prices, nil return prices, nil
} }
@ -96,7 +96,7 @@ func getCardNameByCommand(command string) (string, error) {
} }
func handleConfirmation(c *gin.Context, req *MessageRequest) { func handleConfirmation(c *gin.Context, req *MessageRequest) {
if (req.Type == "confirmation") && (req.GroupId == GROUPID) { if (req.Type == "confirmation") && (req.GroupId == GroupId) {
c.String(http.StatusOK, CONFIRMATION_STRING) c.String(http.StatusOK, ConfirmationString)
} }
} }

View file

@ -1,6 +1,7 @@
package vk package vk
import ( import (
"log"
"math/rand" "math/rand"
"net/http" "net/http"
"net/url" "net/url"
@ -8,17 +9,20 @@ import (
"strings" "strings"
) )
const VKURL = "https://api.vk.com/method/messages.send" const SendMessageUrl = "https://api.vk.com/method/messages.send"
func Message(userId int64, message string) { func Message(userId int64, message string) {
randomId := rand.Int31() randomId := rand.Int31()
params := []string{ params := []string{
"access_token=" + TOKEN, "access_token=" + Token,
"peer_id=" + strconv.FormatInt(userId, 10), "peer_id=" + strconv.FormatInt(userId, 10),
"message=" + url.QueryEscape(message), "message=" + url.QueryEscape(message),
"v=5.95", "v=5.95",
"random_id=" + strconv.FormatInt(int64(randomId), 10), "random_id=" + strconv.FormatInt(int64(randomId), 10),
} }
paramString := strings.Join(params, "&") paramString := strings.Join(params, "&")
http.Get(VKURL + "?" + paramString) resp, err := http.Get(SendMessageUrl + "?" + paramString)
if err != nil || resp.StatusCode != http.StatusOK {
log.Print("Could not send message\n user: %lld", userId)
}
} }

View file

@ -5,7 +5,7 @@ import (
"strconv" "strconv"
) )
var TOKEN = os.Getenv("VK_TOKEN") var Token = os.Getenv("VK_TOKEN")
var SECRET_KEY = os.Getenv("VK_SECRET_KEY") var SecretKey = os.Getenv("VK_SECRET_KEY")
var GROUPID, _ = strconv.ParseInt(os.Getenv("VK_GROUP_ID"), 10, 64) var GroupId, _ = strconv.ParseInt(os.Getenv("VK_GROUP_ID"), 10, 64)
var CONFIRMATION_STRING = os.Getenv("VK_CONFIRMATION_STRING") var ConfirmationString = os.Getenv("VK_CONFIRMATION_STRING")