将 QR 推送到客户端

huangapple go评论90阅读模式
英文:

Pushing QR to client

问题

尝试将登录界面制作成类似WhatsApp的样式,其中二维码被推送到客户端进行扫描,所以我编写了以下服务器代码:

package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	_ "github.com/mattn/go-sqlite3"
	"github.com/skip2/go-qrcode"
	"google.golang.org/protobuf/proto"

	"go.mau.fi/whatsmeow"
	"go.mau.fi/whatsmeow/store"
	"go.mau.fi/whatsmeow/store/sqlstore"
	"go.mau.fi/whatsmeow/types/events"
	waLog "go.mau.fi/whatsmeow/util/log"
)

func eventHandler(evt interface{}) {
	switch v := evt.(type) {
	case *events.Message:
		fmt.Println("Received a message!", v.Message.GetConversation())
	}
}

func main() {
	passer := &DataPasser{logs: make(chan string)}

	http.HandleFunc("/", passer.handleHello)
	go http.ListenAndServe(":9999", nil)

	store.DeviceProps.Os = proto.String("WhatsApp GO")
	dbLog := waLog.Stdout("Database", "DEBUG", true)
	// 确保添加适当的数据库连接器导入,例如 github.com/mattn/go-sqlite3 用于 SQLite
	container, err := sqlstore.New("sqlite3", "file:datastore.db?_foreign_keys=on", dbLog)
	if err != nil {
		panic(err)
	}
	// 如果您想要多个会话,请记住它们的 JID 并使用 .GetDevice(jid) 或 .GetAllDevices() 代替。
	deviceStore, err := container.GetFirstDevice()
	if err != nil {
		panic(err)
	}
	clientLog := waLog.Stdout("Client", "DEBUG", true)
	client := whatsmeow.NewClient(deviceStore, clientLog)
	client.AddEventHandler(eventHandler)

	if client.Store.ID == nil {
		// 未存储 ID,新登录
		qrChan, _ := client.GetQRChannel(context.Background())
		err = client.Connect()
		if err != nil {
			panic(err)
		}

		for evt := range qrChan {
			switch evt.Event {
			case "success":
				{
					passer.logs <- "success"
					fmt.Println("Login event: success")
				}
			case "timeout":
				{
					passer.logs <- "timeout"
					fmt.Println("Login event: timeout")
				}
			case "code":
				{
					passer.logs <- "new code"
					fmt.Println("new code recieved")
					img, err := qrcode.Encode(evt.Code, qrcode.Medium, 200) // evt.Code
					if err != nil {
						fmt.Println("error when write qrImage", err.Error())
					}
					passer.logs <- string(img)
				}
			}
		}
	} else {
		// 已登录,只需连接
		passer.logs <- "Already logged"
		fmt.Println("Already logged")
		err = client.Connect()
		if err != nil {
			panic(err)
		}
	}

	// 监听 Ctrl+C(您也可以执行其他阻止程序退出的操作)
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	<-c

	client.Disconnect()
}

使用以下 API:

package main

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"sync"
)

var (
	mux sync.Mutex
)

type Result struct {
	ResultType, Result string
}

type DataPasser struct {
	logs chan string
}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
	setupCORS(&w, r)
	w.Header().Set("Content-Type", "text/event-stream")
	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Internal error", 500)
		return
	}
	flusher.Flush()
	done := r.Context().Done()
	defer fmt.Println("EXIT")
	for {
		select {
		case <-done:
			// 客户端断开连接
			return
		case m := <-p.logs:
			fmt.Println(m)
			if m == "new code" || m == "We are logging in" || m == "Already logged" || m == "timeout" || m == "success" {
				if _, err := fmt.Fprintf(w, "data: %s\n\n", m); err != nil {
					// 写入连接失败。后续写入可能会失败。
					return
				}
				flusher.Flush()
			} else {
				mux.Lock()

				buffer := bytes.NewBuffer([]byte(m))

				/*	img, _, err := image.Decode(buffer)
					if err != nil {
						fmt.Println("err: ", err)
					}

					if err := jpeg.Encode(buffer, img, nil); err != nil {
						log.Println("unable to encode image.")
					} */

				w.Header().Set("Content-Type", "image/jpeg")
				w.Header().Set("Content-Length", strconv.Itoa(len(buffer.Bytes())))
				if _, err := w.Write(buffer.Bytes()); err != nil {
					log.Println("unable to write image.")
				}
				mux.Unlock()
				flusher.Flush()
			}
		}
	}
}

func setupCORS(w *http.ResponseWriter, req *http.Request) {
	(*w).Header().Set("Cache-Control", "no-cache")
	(*w).Header().Set("Connection", "keep-alive")
	(*w).Header().Set("Access-Control-Allow-Origin", "*")
	(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

但在客户端中无法读取它,我尝试了以下内容,但迷失了:

<html>
<head></head>
<body>
note: <span id="content"></span><br>
<img id="photo" style="display: block;-webkit-user-select: none;">
</body>
<script>
/*  (function(){
document.getElementById("content").innerHTML='<object type="text/html" data="http://localhost:9999/"></object>';
})(); 
*/
const myRequest = new Request('http://127.0.0.1:9999/', {
method: 'GET',
headers: new Headers(),
type: "arraybuffer",
mode: 'cors',
cache: 'default',
});  
var source = new EventSource("http://127.0.0.1:9999/");
source.onmessage = function (event) {
console.log(event)
var counter = event.data; // JSON.parse(event.data);
document.getElementById("content").innerHTML = counter;
}
fetch(myRequest).then(response => {
console.log(response)
console.log(response.headers)
const contentType = response.headers.get("content-type");
if (contentType && contentType.indexOf("application/json") !== -1) {
return response.json().then(data => {
var obj = JSON.parse(str);
console.log(obj)
// Process your data as a JavaScript object
});
}  if (contentType && contentType.indexOf("image/jpeg") !== -1) {
console.log("Image received")
return response.blob().then(data => {
var reader = new FileReader();
reader.readAsDataURL(blob); 
reader.onloadend = function() {
var imageUrl = reader.result;                
var img = document.querySelector("#photo");
img.src = imageUrl;
}
});
} else if (contentType && contentType.indexOf("text/event-stream") !== -1) {
return response.text().then(text => {
console.log(text)
var source = new EventSource("http://localhost:9999/");
source.onmessage = function (event) {
var response = event.data // JSON.parse(event.data);
document.getElementById("content").innerHTML = counter;
} 
// Process your text as a String
});
} else if (contentType && contentType.indexOf("text/html") !== -1) {
return response.text().then(text => {
console.log(text)
var source = new EventSource("http://localhost:9999/");
source.onmessage = function (event) {
var response = event.data // JSON.parse(event.data);
document.getElementById("content").innerHTML = counter;
} 
// Process your text as a String
});
} 
});
</script>
</html>

如果我运行并查看显示的页面,我会看到:

将 QR 推送到客户端

有什么帮助吗?

英文:

Trying to make login screen as WhatsApp, where the QR is pushed to the client for scanning, so I wrote the below server code:

package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;os&quot;
	&quot;os/signal&quot;
	&quot;syscall&quot;

	_ &quot;github.com/mattn/go-sqlite3&quot;
	&quot;github.com/skip2/go-qrcode&quot;
	&quot;google.golang.org/protobuf/proto&quot;

	&quot;go.mau.fi/whatsmeow&quot;
	&quot;go.mau.fi/whatsmeow/store&quot;
	&quot;go.mau.fi/whatsmeow/store/sqlstore&quot;
	&quot;go.mau.fi/whatsmeow/types/events&quot;
	waLog &quot;go.mau.fi/whatsmeow/util/log&quot;
)

func eventHandler(evt interface{}) {
	switch v := evt.(type) {
	case *events.Message:
		fmt.Println(&quot;Received a message!&quot;, v.Message.GetConversation())
	}
}

func main() {
	passer := &amp;DataPasser{logs: make(chan string)}

	http.HandleFunc(&quot;/&quot;, passer.handleHello)
	go http.ListenAndServe(&quot;:9999&quot;, nil)

	store.DeviceProps.Os = proto.String(&quot;WhatsApp GO&quot;)
	dbLog := waLog.Stdout(&quot;Database&quot;, &quot;DEBUG&quot;, true)
	// Make sure you add appropriate DB connector imports, e.g. github.com/mattn/go-sqlite3 for SQLite
	container, err := sqlstore.New(&quot;sqlite3&quot;, &quot;file:datastore.db?_foreign_keys=on&quot;, dbLog)
	if err != nil {
		panic(err)
	}
	// If you want multiple sessions, remember their JIDs and use .GetDevice(jid) or .GetAllDevices() instead.
	deviceStore, err := container.GetFirstDevice()
	if err != nil {
		panic(err)
	}
	clientLog := waLog.Stdout(&quot;Client&quot;, &quot;DEBUG&quot;, true)
	client := whatsmeow.NewClient(deviceStore, clientLog)
	client.AddEventHandler(eventHandler)

	if client.Store.ID == nil {
		// No ID stored, new login
		qrChan, _ := client.GetQRChannel(context.Background())
		err = client.Connect()
		if err != nil {
			panic(err)
		}

		for evt := range qrChan {
			switch evt.Event {
			case &quot;success&quot;:
				{
					passer.logs &lt;- &quot;success&quot;
					fmt.Println(&quot;Login event: success&quot;)
				}
			case &quot;timeout&quot;:
				{
					passer.logs &lt;- &quot;timeout&quot;
					fmt.Println(&quot;Login event: timeout&quot;)
				}
			case &quot;code&quot;:
				{
					passer.logs &lt;- &quot;new code&quot;
					fmt.Println(&quot;new code recieved&quot;)
					img, err := qrcode.Encode(evt.Code, qrcode.Medium, 200) // evt.Code
					if err != nil {
						fmt.Println(&quot;error when write qrImage&quot;, err.Error())
					}
					passer.logs &lt;- string(img)
				}
			}
		}
	} else {
		// Already logged in, just connect
		passer.logs &lt;- &quot;Already logged&quot;
		fmt.Println(&quot;Already logged&quot;)
		err = client.Connect()
		if err != nil {
			panic(err)
		}
	}

	// Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	&lt;-c

	client.Disconnect()
}

With the below api:

package main

import (
	&quot;bytes&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;strconv&quot;
	&quot;sync&quot;
)

var (
	mux sync.Mutex
)

type Result struct {
	ResultType, Result string
}

type DataPasser struct {
	logs chan string
}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
	setupCORS(&amp;w, r)
	w.Header().Set(&quot;Content-Type&quot;, &quot;text/event-stream&quot;)
	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, &quot;Internal error&quot;, 500)
		return
	}
	flusher.Flush()
	done := r.Context().Done()
	defer fmt.Println(&quot;EXIT&quot;)
	for {
		select {
		case &lt;-done:
			// the client disconnected
			return
		case m := &lt;-p.logs:
			fmt.Println(m)
			if m == &quot;new code&quot; || m == &quot;We are logging in&quot; || m == &quot;Already logged&quot; || m == &quot;timeout&quot; || m == &quot;success&quot; {
				if _, err := fmt.Fprintf(w, &quot;data: %s\n\n&quot;, m); err != nil {
					// Write to connection failed. Subsequent writes will probably fail.
					return
				}
				flusher.Flush()
			} else {
				mux.Lock()

				buffer := bytes.NewBuffer([]byte(m))

				/*	img, _, err := image.Decode(buffer)
					if err != nil {
						fmt.Println(&quot;err: &quot;, err)
					}

					if err := jpeg.Encode(buffer, img, nil); err != nil {
						log.Println(&quot;unable to encode image.&quot;)
					} */

				w.Header().Set(&quot;Content-Type&quot;, &quot;image/jpeg&quot;)
				w.Header().Set(&quot;Content-Length&quot;, strconv.Itoa(len(buffer.Bytes())))
				if _, err := w.Write(buffer.Bytes()); err != nil {
					log.Println(&quot;unable to write image.&quot;)
				}
				mux.Unlock()
				flusher.Flush()
			}
		}
	}
}

func setupCORS(w *http.ResponseWriter, req *http.Request) {
	(*w).Header().Set(&quot;Cache-Control&quot;, &quot;no-cache&quot;)
	(*w).Header().Set(&quot;Connection&quot;, &quot;keep-alive&quot;)
	(*w).Header().Set(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;)
	(*w).Header().Set(&quot;Access-Control-Allow-Methods&quot;, &quot;POST, GET, OPTIONS, PUT, DELETE&quot;)
	(*w).Header().Set(&quot;Access-Control-Allow-Headers&quot;, &quot;Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization&quot;)
}

But stuck to read it in the client, I tried something as below, but got lost:

&lt;html&gt;
&lt;head&gt;&lt;/head&gt;
&lt;body&gt;
note: &lt;span id=&quot;content&quot;&gt;&lt;/span&gt;&lt;br&gt;
&lt;img id=&quot;photo&quot; style=&quot;display: block;-webkit-user-select: none;&quot;&gt;
&lt;/body&gt;
&lt;script&gt;
/*  (function(){
document.getElementById(&quot;content&quot;).innerHTML=&#39;&lt;object type=&quot;text/html&quot; data=&quot;http://localhost:9999/&quot; &gt;&lt;/object&gt;&#39;;
})(); 
*/
const myRequest = new Request(&#39;http://127.0.0.1:9999/&#39;, {
method: &#39;GET&#39;,
headers: new Headers(),
type: &quot;arraybuffer&quot;,
mode: &#39;cors&#39;,
cache: &#39;default&#39;,
});  
var source = new EventSource(&quot;http://127.0.0.1:9999/&quot;);
source.onmessage = function (event) {
console.log(event)
var counter = event.data; // JSON.parse(event.data);
document.getElementById(&quot;content&quot;).innerHTML = counter;
}
fetch(myRequest).then(response =&gt; {
console.log(response)
console.log(response.headers)
const contentType = response.headers.get(&quot;content-type&quot;);
if (contentType &amp;&amp; contentType.indexOf(&quot;application/json&quot;) !== -1) {
return response.json().then(data =&gt; {
var obj = JSON.parse(str);
console.log(obj)
// Process your data as a JavaScript object
});
}  if (contentType &amp;&amp; contentType.indexOf(&quot;image/jpeg&quot;) !== -1) {
console.log(&quot;Image received&quot;)
return response.blob().then(data =&gt; {
var reader = new FileReader();
reader.readAsDataURL(blob); 
reader.onloadend = function() {
var imageUrl = reader.result;                
var img = document.querySelector(&quot;#photo&quot;);
img.src = imageUrl;
}
});
} else if (contentType &amp;&amp; contentType.indexOf(&quot;text/event-stream&quot;) !== -1) {
return response.text().then(text =&gt; {
console.log(text)
var source = new EventSource(&quot;http://localhost:9999/&quot;);
source.onmessage = function (event) {
var response = event.data // JSON.parse(event.data);
document.getElementById(&quot;content&quot;).innerHTML = counter;
} 
// Process your text as a String
});
} else if (contentType &amp;&amp; contentType.indexOf(&quot;text/html&quot;) !== -1) {
return response.text().then(text =&gt; {
console.log(text)
var source = new EventSource(&quot;http://localhost:9999/&quot;);
source.onmessage = function (event) {
var response = event.data // JSON.parse(event.data);
document.getElementById(&quot;content&quot;).innerHTML = counter;
} 
// Process your text as a String
});
} 
});
&lt;/script&gt;
&lt;/html&gt;

If I run and see the displayed page, I see:

将 QR 推送到客户端

Any help?

答案1

得分: 0

我通过将QR字符串推送到服务器,并使用qrcodejs将其转换为QR码来解决了这个问题。如果有兴趣,以下是完整的代码:

// main.go
package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	_ "github.com/mattn/go-sqlite3"
	"google.golang.org/protobuf/proto"

	"go.mau.fi/whatsmeow"
	"go.mau.fi/whatsmeow/store"
	"go.mau.fi/whatsmeow/store/sqlstore"
	"go.mau.fi/whatsmeow/types/events"
	waLog "go.mau.fi/whatsmeow/util/log"
)

func eventHandler(evt interface{}) {
	switch v := evt.(type) {
	case *events.Message:
		fmt.Println("Received a message!", v.Message.GetConversation())
	}
}

func main() {
	passer := &DataPasser{logs: make(chan string)}

	http.HandleFunc("/sse/dashboard", passer.handleHello)
	go http.ListenAndServe(":1234", nil)
	/*
		ticker := time.NewTicker(500 * time.Millisecond)
		defer ticker.Stop()
		done := make(chan bool)
		go func() {
			for {
				select {
				case <-done:
					return
				case <-ticker.C:
					//	fmt.Println("Tick at", t)
					// passer.logs <- buffer.String()
				}
			}
		}()
	*/
	store.DeviceProps.Os = proto.String("WhatsApp GO")
	dbLog := waLog.Stdout("Database", "DEBUG", true)
	// Make sure you add appropriate DB connector imports, e.g. github.com/mattn/go-sqlite3 for SQLite
	container, err := sqlstore.New("sqlite3", "file:datastore.db?_foreign_keys=on", dbLog)
	if err != nil {
		panic(err)
	}
	// If you want multiple sessions, remember their JIDs and use .GetDevice(jid) or .GetAllDevices() instead.
	deviceStore, err := container.GetFirstDevice()
	if err != nil {
		panic(err)
	}
	clientLog := waLog.Stdout("Client", "DEBUG", true)
	client := whatsmeow.NewClient(deviceStore, clientLog)
	client.AddEventHandler(eventHandler)

	if client.Store.ID == nil {
		// No ID stored, new login
		qrChan, _ := client.GetQRChannel(context.Background())
		err = client.Connect()
		if err != nil {
			panic(err)
		}

		for evt := range qrChan {
			switch evt.Event {
			case "success":
				{
					passer.logs <- "success"
					fmt.Println("Login event: success")
				}
			case "timeout":
				{
					passer.logs <- "timeout"
					fmt.Println("Login event: timeout")
				}
			case "code":
				{
					fmt.Println("new code recieved")
					fmt.Println(evt.Code)
					passer.logs <- evt.Code
				}
			}
		}
	} else {
		// Already logged in, just connect
		passer.logs <- "Already logged"
		fmt.Println("Already logged")
		err = client.Connect()
		if err != nil {
			panic(err)
		}
	}

	// Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	<-c

	client.Disconnect()
}

// api.go
package main

import (
	"fmt"
	"net/http"
	"sync"
)

var (
	mux sync.Mutex
)

type DataPasser struct {
	logs chan string
}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
	fmt.Println("from here")
	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Internal error", 500)
		return
	}
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")
	setupCORS(&w, r)

	for {
		select {
		case c := <-p.logs:
			fmt.Println("recieved")
			mux.Lock()
			//counter++
			//c := counter
			mux.Unlock()
			fmt.Fprintf(w, "data: %v\n\n", c)
			flusher.Flush()
		case <-r.Context().Done():
			fmt.Println("Connection closed")
			return
		}
	}
}

func setupCORS(w *http.ResponseWriter, req *http.Request) {
	(*w).Header().Set("Cache-Control", "no-cache")
	(*w).Header().Set("Access-Control-Allow-Origin", "*")
	(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

和客户端代码:

<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
</head>
<body>
<h5>Server message/Code: <span id="message"></span></h5>
<div id="qr"></div>
<script>
var source = new EventSource("http://localhost:1234/sse/dashboard");
source.onmessage = function (event) {
var message = event.data
document.querySelector('#message').innerHTML = message;
if (new String(message).valueOf() == "success" || new String(message).valueOf() == "timeout"
|| new String(message).valueOf() == "Already logged") {
document.querySelector('#qr').innerHTML = "";
} else {
var qrcode = new QRCode("qr", {
text: message,
width: 128,
height: 128,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.M
});
}
}
/*
var qrcode = new QRCode(
"qr",
[
"BEGIN:VCARD",
"VERSION:2.1",
"N:Doe;John;;Dr;",
"FN:Dr. John Doe",
"EMAIL:johndoe@hotmail.com",
"TEL;TYPE=cell:(123) 555-5832",
"END:VCARD"
].join("\r\n")
); */
</script>
</body>
</html>
英文:

I solved it buy pushing the QR string t o the server, and convert it to QR using qrcodejs. My full code if any is interested is:

// main.go
package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;os&quot;
	&quot;os/signal&quot;
	&quot;syscall&quot;

	_ &quot;github.com/mattn/go-sqlite3&quot;
	&quot;google.golang.org/protobuf/proto&quot;

	&quot;go.mau.fi/whatsmeow&quot;
	&quot;go.mau.fi/whatsmeow/store&quot;
	&quot;go.mau.fi/whatsmeow/store/sqlstore&quot;
	&quot;go.mau.fi/whatsmeow/types/events&quot;
	waLog &quot;go.mau.fi/whatsmeow/util/log&quot;
)

func eventHandler(evt interface{}) {
	switch v := evt.(type) {
	case *events.Message:
		fmt.Println(&quot;Received a message!&quot;, v.Message.GetConversation())
	}
}

func main() {
	passer := &amp;DataPasser{logs: make(chan string)}

	http.HandleFunc(&quot;/sse/dashboard&quot;, passer.handleHello)
	go http.ListenAndServe(&quot;:1234&quot;, nil)
	/*
		ticker := time.NewTicker(500 * time.Millisecond)
		defer ticker.Stop()
		done := make(chan bool)
		go func() {
			for {
				select {
				case &lt;-done:
					return
				case &lt;-ticker.C:
					//	fmt.Println(&quot;Tick at&quot;, t)
					// passer.logs &lt;- buffer.String()
				}
			}
		}()
	*/
	store.DeviceProps.Os = proto.String(&quot;WhatsApp GO&quot;)
	dbLog := waLog.Stdout(&quot;Database&quot;, &quot;DEBUG&quot;, true)
	// Make sure you add appropriate DB connector imports, e.g. github.com/mattn/go-sqlite3 for SQLite
	container, err := sqlstore.New(&quot;sqlite3&quot;, &quot;file:datastore.db?_foreign_keys=on&quot;, dbLog)
	if err != nil {
		panic(err)
	}
	// If you want multiple sessions, remember their JIDs and use .GetDevice(jid) or .GetAllDevices() instead.
	deviceStore, err := container.GetFirstDevice()
	if err != nil {
		panic(err)
	}
	clientLog := waLog.Stdout(&quot;Client&quot;, &quot;DEBUG&quot;, true)
	client := whatsmeow.NewClient(deviceStore, clientLog)
	client.AddEventHandler(eventHandler)

	if client.Store.ID == nil {
		// No ID stored, new login
		qrChan, _ := client.GetQRChannel(context.Background())
		err = client.Connect()
		if err != nil {
			panic(err)
		}

		for evt := range qrChan {
			switch evt.Event {
			case &quot;success&quot;:
				{
					passer.logs &lt;- &quot;success&quot;
					fmt.Println(&quot;Login event: success&quot;)
				}
			case &quot;timeout&quot;:
				{
					passer.logs &lt;- &quot;timeout&quot;
					fmt.Println(&quot;Login event: timeout&quot;)
				}
			case &quot;code&quot;:
				{
					fmt.Println(&quot;new code recieved&quot;)
					fmt.Println(evt.Code)
					passer.logs &lt;- evt.Code
				}
			}
		}
	} else {
		// Already logged in, just connect
		passer.logs &lt;- &quot;Already logged&quot;
		fmt.Println(&quot;Already logged&quot;)
		err = client.Connect()
		if err != nil {
			panic(err)
		}
	}

	// Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	&lt;-c

	client.Disconnect()
}

And

// api.go
package main

import (
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;sync&quot;
)

var (
	mux sync.Mutex
)

type DataPasser struct {
	logs chan string
}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
	fmt.Println(&quot;from here&quot;)
	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, &quot;Internal error&quot;, 500)
		return
	}
	w.Header().Set(&quot;Content-Type&quot;, &quot;text/event-stream&quot;)
	w.Header().Set(&quot;Cache-Control&quot;, &quot;no-cache&quot;)
	w.Header().Set(&quot;Connection&quot;, &quot;keep-alive&quot;)
	setupCORS(&amp;w, r)

	for {
		select {
		case c := &lt;-p.logs:
			fmt.Println(&quot;recieved&quot;)
			mux.Lock()
			//counter++
			//c := counter
			mux.Unlock()
			fmt.Fprintf(w, &quot;data: %v\n\n&quot;, c)
			flusher.Flush()
		case &lt;-r.Context().Done():
			fmt.Println(&quot;Connection closed&quot;)
			return
		}
	}
}

func setupCORS(w *http.ResponseWriter, req *http.Request) {
	(*w).Header().Set(&quot;Cache-Control&quot;, &quot;no-cache&quot;)
	(*w).Header().Set(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;)
	(*w).Header().Set(&quot;Access-Control-Allow-Methods&quot;, &quot;POST, GET, OPTIONS, PUT, DELETE&quot;)
	(*w).Header().Set(&quot;Access-Control-Allow-Headers&quot;, &quot;Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization&quot;)
}

And the client side is:

&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
&lt;script src=&quot;https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h5&gt;Server message/Code: &lt;span id=&quot;message&quot;&gt;&lt;/span&gt;&lt;/h5&gt;
&lt;div id=&quot;qr&quot;&gt;&lt;/div&gt;
&lt;script&gt;
var source = new EventSource(&quot;http://localhost:1234/sse/dashboard&quot;);
source.onmessage = function (event) {
var message = event.data
document.querySelector(&#39;#message&#39;).innerHTML = message;
if (new String(message).valueOf() == &quot;success&quot; || new String(message).valueOf() == &quot;timeout&quot;
|| new String(message).valueOf() == &quot;Already logged&quot;) {
document.querySelector(&#39;#qr&#39;).innerHTML = &quot;&quot;;
} else {
var qrcode = new QRCode(&quot;qr&quot;, {
text: message,
width: 128,
height: 128,
colorDark : &quot;#000000&quot;,
colorLight : &quot;#ffffff&quot;,
correctLevel : QRCode.CorrectLevel.M
});
}
}
/*
var qrcode = new QRCode(
&quot;qr&quot;,
[
&quot;BEGIN:VCARD&quot;,
&quot;VERSION:2.1&quot;,
&quot;N:Doe;John;;Dr;&quot;,
&quot;FN:Dr. John Doe&quot;,
&quot;EMAIL:johndoe@hotmail.com&quot;,
&quot;TEL;TYPE=cell:(123) 555-5832&quot;,
&quot;END:VCARD&quot;
].join(&quot;\r\n&quot;)
); */
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

huangapple
  • 本文由 发表于 2022年6月13日 05:47:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/72596131.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定