Переглянути джерело

Merge branch 'develop' of http://git.hiwavo.com/Fohow/fohow_api

abiao 1 місяць тому
батько
коміт
ebd044ad0d

+ 286 - 0
go/gopath/src/fohow.com/apps/controllers/tool_controller/qrcode_controller.go.bak.20260601_1703

@@ -0,0 +1,286 @@
+package tool_controller
+
+import (
+	"bytes"
+	"context"
+	"fmt"
+	"image"
+	_ "image/jpeg"
+	_ "image/png"
+	"strings"
+	"time"
+
+	"github.com/chromedp/chromedp"
+
+	// "os"
+	"net/http"
+	"net/url"
+	// "strings"
+
+	"github.com/astaxie/beego"
+	// "github.com/astaxie/beego/context"
+	"fohow.com/apps"
+	"github.com/go-wkhtmltoimage"
+	"github.com/skip2/go-qrcode"
+	// "fohow.com/apps"
+	// "api.com/apps/controllers/user_controller"
+	// "api.com/apps/models/order_model"
+	// "api.com/apps/models/product_model"
+	// "api.com/apps/models/vas_model"
+	// qrcode "github.com/skip2/go-qrcode"
+)
+
+func (self *ToolController) GetHaibao() {
+	uri := self.GetString("url")
+	// if !isWhiteUrl(uri) {
+	// 	beego.BeeLogger.Error("BlackUrl=%s", uri)
+	// 	self.ReturnError(403, apps.BlackUrl, "", nil)
+	// }
+	h, _ := self.GetInt("h")
+	w, _ := self.GetInt("w")
+	q, _ := self.GetInt("q")
+	if h <= 0 {
+		h = 0 //default 0
+	}
+	if w <= 0 {
+		w = 1024 //default 1024
+	}
+	if q <= 0 {
+		q = 94 //0-100, default 94
+	}
+	c := wkhtmltoimage.ImageOptions{
+		BinaryPath: beego.AppConfig.String("WkhtmltoimgBinPath"),
+		Input:      uri,
+		Height:     h,
+		Width:      w,
+		Quality:    q,
+		Format:     "png"}
+	out, _ := wkhtmltoimage.GenerateImage(&c)
+	self.Ctx.Output.Header("Content-Type", "image/png; charset=utf-8")
+	self.Ctx.Output.Body(out)
+}
+
+func (self *ToolController) GetHaibaoWithGoogle() {
+	uri := self.GetString("url")
+
+	// URL 解码
+	decodedUri, err := url.QueryUnescape(uri)
+	if err != nil {
+		beego.BeeLogger.Warning("GetHaibaoWithGoogle decode url failed: err=[%s] raw_url=[%s]", err, maskURLForLog(uri))
+		self.ReturnError(400, apps.ParamsError, "", nil)
+		return
+	}
+
+	beego.BeeLogger.Info("GetHaibaoWithGoogle start url=[%s]", maskURLForLog(decodedUri))
+	//title := self.GetString("title")
+	// 创建上下文
+	ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithErrorf(chromedpErrorLogf))
+	defer cancel()
+
+	// 设置超时时间
+	ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
+	defer cancel()
+
+	// 运行任务(导航到网页,并捕获屏幕截图)
+	err = chromedp.Run(ctx,
+		chromedp.EmulateViewport(1400, 800), // 设置视口宽度为 1400,高度为 800
+		chromedp.Navigate(decodedUri),       // 替换为你想截图的网页地址
+		chromedp.WaitReady("body", chromedp.ByQuery),
+	)
+	if err != nil {
+		beego.BeeLogger.Error("GetHaibaoWithGoogle screenshot failed: err=[%s] url=[%s]", err, maskURLForLog(decodedUri))
+		self.ReturnError(504, apps.NetworkBusy, "", nil)
+		return
+	}
+	buf, err := captureNonBlankScreenshot(ctx, maskURLForLog(decodedUri), 60)
+	if err != nil {
+		beego.BeeLogger.Error("GetHaibaoWithGoogle screenshot failed: err=[%s] url=[%s]", err, maskURLForLog(decodedUri))
+		self.ReturnError(504, apps.NetworkBusy, "", nil)
+		return
+	}
+
+	beego.BeeLogger.Info("GetHaibaoWithGoogle success url=[%s] bytes=[%d]", maskURLForLog(decodedUri), len(buf))
+	self.Ctx.Output.Header("Content-Type", http.DetectContentType(buf))
+	self.Ctx.Output.Body(buf)
+
+	//log.Println("Screenshot saved as screenshot.png")
+}
+
+func (self *ToolController) GetOtherHaibaoWithGoogle() {
+	uri := self.GetString("url")
+
+	// URL 解码
+	decodedUri, err := url.QueryUnescape(uri)
+	if err != nil {
+		beego.BeeLogger.Warning("GetOtherHaibaoWithGoogle decode url failed: err=[%s] raw_url=[%s]", err, maskURLForLog(uri))
+		self.ReturnError(400, apps.ParamsError, "", nil)
+		return
+	}
+
+	beego.BeeLogger.Info("GetOtherHaibaoWithGoogle start url=[%s]", maskURLForLog(decodedUri))
+	//title := self.GetString("title")
+	// 创建上下文
+	ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithErrorf(chromedpErrorLogf))
+	defer cancel()
+
+	// 设置超时时间
+	ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
+	defer cancel()
+
+	// 运行任务(导航到网页,并捕获屏幕截图)
+	err = chromedp.Run(ctx,
+		chromedp.EmulateViewport(1400, 800),          // 设置视口宽度为 1400,高度为 800
+		chromedp.Navigate(decodedUri),                // 替换为你想截图的网页地址
+		chromedp.WaitReady("body", chromedp.ByQuery), // 等待页面的 <body> 元素加载完成
+	)
+	if err != nil {
+		beego.BeeLogger.Error("GetOtherHaibaoWithGoogle screenshot failed: err=[%s] url=[%s]", err, maskURLForLog(decodedUri))
+		self.ReturnError(504, apps.NetworkBusy, "", nil)
+		return
+	}
+	buf, err := captureNonBlankScreenshot(ctx, maskURLForLog(decodedUri), 90)
+	if err != nil {
+		beego.BeeLogger.Error("GetOtherHaibaoWithGoogle screenshot failed: err=[%s] url=[%s]", err, maskURLForLog(decodedUri))
+		self.ReturnError(504, apps.NetworkBusy, "", nil)
+		return
+	}
+
+	beego.BeeLogger.Info("GetOtherHaibaoWithGoogle success url=[%s] bytes=[%d]", maskURLForLog(decodedUri), len(buf))
+	self.Ctx.Output.Header("Content-Type", http.DetectContentType(buf))
+	self.Ctx.Output.Body(buf)
+
+	//log.Println("Screenshot saved as screenshot.png")
+}
+
+func (self *ToolController) GetQrcode() {
+	uri := self.GetString("url")
+	// if !isWhiteUrl(uri) {
+	// 	beego.BeeLogger.Error("BlackUrl=%s", uri)
+	// 	self.ReturnError(403, apps.BlackUrl, "", nil)
+	// }
+	size, _ := self.GetInt("size")
+	if size <= 0 {
+		size = 256 //default 0
+	}
+	png, _ := createQrcode(uri, size)
+	self.Ctx.Output.Header("Content-Type", "image/png; charset=utf-8")
+	self.Ctx.Output.Body(png)
+}
+
+func createQrcode(uri string, size int) ([]byte, error) {
+	png, err := qrcode.Encode(uri, qrcode.Medium, size)
+	return png, err
+}
+func isWhiteUrl(uri string) bool {
+	if beego.AppConfig.String("RunMode") == "dev" {
+		return true
+	}
+	_uri, _ := url.Parse(uri)
+	checkUri := fmt.Sprintf("%s://%s", _uri.Scheme, _uri.Host)
+	var urls []string
+	urls = append(urls, beego.AppConfig.String("WxHost"))
+	urls = append(urls, beego.AppConfig.String("ApiHost"))
+	urls = append(urls, beego.AppConfig.String("RailsHost"))
+	urls = append(urls, "http://tapi.d5c360.com")
+	urls = append(urls, "https://m.d5ct.com")
+	urls = append(urls, "http://m.d5c360.com")
+	urls = append(urls, "http://www.d5c360.com")
+	urls = append(urls, "http://testadmin.zhppp.com")
+	urls = append(urls, "http://weixin.qq.com")
+	for _, v := range urls {
+		if v == checkUri {
+			return true
+		}
+	}
+	return false
+}
+
+func maskURLForLog(rawURL string) string {
+	if rawURL == "" {
+		return ""
+	}
+	u, err := url.Parse(rawURL)
+	if err != nil {
+		return rawURL
+	}
+	q := u.Query()
+	if q.Get("token") != "" {
+		q.Set("token", "***")
+	}
+	u.RawQuery = q.Encode()
+	return u.String()
+}
+
+func chromedpErrorLogf(format string, args ...interface{}) {
+	msg := fmt.Sprintf(format, args...)
+	if strings.Contains(msg, "could not unmarshal event") {
+		return
+	}
+	beego.BeeLogger.Error("chromedp error: %s", msg)
+}
+
+func captureNonBlankScreenshot(ctx context.Context, safeURL string, quality int) ([]byte, error) {
+	waitPlan := []time.Duration{
+		3 * time.Second,
+		3 * time.Second,
+		5 * time.Second,
+		8 * time.Second,
+		10 * time.Second,
+	}
+	var last []byte
+	for attempt, wait := range waitPlan {
+		var buf []byte
+		if err := chromedp.Run(ctx,
+			chromedp.Sleep(wait),
+			chromedp.FullScreenshot(&buf, quality),
+		); err != nil {
+			return nil, err
+		}
+		last = buf
+		if !isBlankScreenshot(buf) {
+			if attempt > 0 {
+				beego.BeeLogger.Info("haibao screenshot ready after retry url=[%s] attempt=[%d] bytes=[%d]", safeURL, attempt+1, len(buf))
+			}
+			return buf, nil
+		}
+		beego.BeeLogger.Warning("haibao screenshot blank, retry url=[%s] attempt=[%d] bytes=[%d]", safeURL, attempt+1, len(buf))
+	}
+	return nil, fmt.Errorf("screenshot stayed blank after retries, last_bytes=%d", len(last))
+}
+
+func isBlankScreenshot(data []byte) bool {
+	if len(data) == 0 {
+		return true
+	}
+	img, _, err := image.Decode(bytes.NewReader(data))
+	if err != nil {
+		return false
+	}
+	bounds := img.Bounds()
+	width := bounds.Dx()
+	height := bounds.Dy()
+	if width <= 0 || height <= 0 {
+		return true
+	}
+	stepX := maxInt(width/90, 1)
+	stepY := maxInt(height/90, 1)
+	total := 0
+	nonWhite := 0
+	for y := bounds.Min.Y; y < bounds.Max.Y; y += stepY {
+		for x := bounds.Min.X; x < bounds.Max.X; x += stepX {
+			r, g, b, _ := img.At(x, y).RGBA()
+			total++
+			if uint8(r>>8) < 245 || uint8(g>>8) < 245 || uint8(b>>8) < 245 {
+				nonWhite++
+			}
+		}
+	}
+	return total == 0 || float64(nonWhite)/float64(total) < 0.001
+}
+
+func maxInt(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}

+ 4 - 0
go/gopath/src/fohow.com/apps/models/user_model/wx_user.go

@@ -78,6 +78,7 @@ func (self *WxUser) TableName() string {
 }
 
 func (self *WxUser) QuickCreate(openid, unionid, ip string, userId, inviteId, introUserId, depart int64) *WxUser {
+	vipEndDate := time.Now().AddDate(1, 0, 0)
 	item := &WxUser{
 		UserId:      userId,
 		Openid:      openid,
@@ -92,6 +93,9 @@ func (self *WxUser) QuickCreate(openid, unionid, ip string, userId, inviteId, in
 		beego.BeeLogger.Error("QuickCreate WxUser err=[%s]", err)
 		return nil
 	}
+	if _, updateErr := orm.NewOrm().Raw("UPDATE wx_users SET vip_rank = ?, vip_end_date = ? WHERE id = ?", WX_USER_RANK_THERE, vipEndDate, id).Exec(); updateErr != nil {
+		beego.BeeLogger.Error("update WxUser vip rank err=[%s]", updateErr)
+	}
 	item.Id = id
 	return item
 }