将 QR 推送到客户端

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

Pushing QR to client

问题

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

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "os/signal"
  8. "syscall"
  9. _ "github.com/mattn/go-sqlite3"
  10. "github.com/skip2/go-qrcode"
  11. "google.golang.org/protobuf/proto"
  12. "go.mau.fi/whatsmeow"
  13. "go.mau.fi/whatsmeow/store"
  14. "go.mau.fi/whatsmeow/store/sqlstore"
  15. "go.mau.fi/whatsmeow/types/events"
  16. waLog "go.mau.fi/whatsmeow/util/log"
  17. )
  18. func eventHandler(evt interface{}) {
  19. switch v := evt.(type) {
  20. case *events.Message:
  21. fmt.Println("Received a message!", v.Message.GetConversation())
  22. }
  23. }
  24. func main() {
  25. passer := &DataPasser{logs: make(chan string)}
  26. http.HandleFunc("/", passer.handleHello)
  27. go http.ListenAndServe(":9999", nil)
  28. store.DeviceProps.Os = proto.String("WhatsApp GO")
  29. dbLog := waLog.Stdout("Database", "DEBUG", true)
  30. // 确保添加适当的数据库连接器导入,例如 github.com/mattn/go-sqlite3 用于 SQLite
  31. container, err := sqlstore.New("sqlite3", "file:datastore.db?_foreign_keys=on", dbLog)
  32. if err != nil {
  33. panic(err)
  34. }
  35. // 如果您想要多个会话,请记住它们的 JID 并使用 .GetDevice(jid) 或 .GetAllDevices() 代替。
  36. deviceStore, err := container.GetFirstDevice()
  37. if err != nil {
  38. panic(err)
  39. }
  40. clientLog := waLog.Stdout("Client", "DEBUG", true)
  41. client := whatsmeow.NewClient(deviceStore, clientLog)
  42. client.AddEventHandler(eventHandler)
  43. if client.Store.ID == nil {
  44. // 未存储 ID,新登录
  45. qrChan, _ := client.GetQRChannel(context.Background())
  46. err = client.Connect()
  47. if err != nil {
  48. panic(err)
  49. }
  50. for evt := range qrChan {
  51. switch evt.Event {
  52. case "success":
  53. {
  54. passer.logs <- "success"
  55. fmt.Println("Login event: success")
  56. }
  57. case "timeout":
  58. {
  59. passer.logs <- "timeout"
  60. fmt.Println("Login event: timeout")
  61. }
  62. case "code":
  63. {
  64. passer.logs <- "new code"
  65. fmt.Println("new code recieved")
  66. img, err := qrcode.Encode(evt.Code, qrcode.Medium, 200) // evt.Code
  67. if err != nil {
  68. fmt.Println("error when write qrImage", err.Error())
  69. }
  70. passer.logs <- string(img)
  71. }
  72. }
  73. }
  74. } else {
  75. // 已登录,只需连接
  76. passer.logs <- "Already logged"
  77. fmt.Println("Already logged")
  78. err = client.Connect()
  79. if err != nil {
  80. panic(err)
  81. }
  82. }
  83. // 监听 Ctrl+C(您也可以执行其他阻止程序退出的操作)
  84. c := make(chan os.Signal, 1)
  85. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  86. <-c
  87. client.Disconnect()
  88. }

使用以下 API:

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "strconv"
  8. "sync"
  9. )
  10. var (
  11. mux sync.Mutex
  12. )
  13. type Result struct {
  14. ResultType, Result string
  15. }
  16. type DataPasser struct {
  17. logs chan string
  18. }
  19. func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
  20. setupCORS(&w, r)
  21. w.Header().Set("Content-Type", "text/event-stream")
  22. flusher, ok := w.(http.Flusher)
  23. if !ok {
  24. http.Error(w, "Internal error", 500)
  25. return
  26. }
  27. flusher.Flush()
  28. done := r.Context().Done()
  29. defer fmt.Println("EXIT")
  30. for {
  31. select {
  32. case <-done:
  33. // 客户端断开连接
  34. return
  35. case m := <-p.logs:
  36. fmt.Println(m)
  37. if m == "new code" || m == "We are logging in" || m == "Already logged" || m == "timeout" || m == "success" {
  38. if _, err := fmt.Fprintf(w, "data: %s\n\n", m); err != nil {
  39. // 写入连接失败。后续写入可能会失败。
  40. return
  41. }
  42. flusher.Flush()
  43. } else {
  44. mux.Lock()
  45. buffer := bytes.NewBuffer([]byte(m))
  46. /* img, _, err := image.Decode(buffer)
  47. if err != nil {
  48. fmt.Println("err: ", err)
  49. }
  50. if err := jpeg.Encode(buffer, img, nil); err != nil {
  51. log.Println("unable to encode image.")
  52. } */
  53. w.Header().Set("Content-Type", "image/jpeg")
  54. w.Header().Set("Content-Length", strconv.Itoa(len(buffer.Bytes())))
  55. if _, err := w.Write(buffer.Bytes()); err != nil {
  56. log.Println("unable to write image.")
  57. }
  58. mux.Unlock()
  59. flusher.Flush()
  60. }
  61. }
  62. }
  63. }
  64. func setupCORS(w *http.ResponseWriter, req *http.Request) {
  65. (*w).Header().Set("Cache-Control", "no-cache")
  66. (*w).Header().Set("Connection", "keep-alive")
  67. (*w).Header().Set("Access-Control-Allow-Origin", "*")
  68. (*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
  69. (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
  70. }

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

  1. <html>
  2. <head></head>
  3. <body>
  4. note: <span id="content"></span><br>
  5. <img id="photo" style="display: block;-webkit-user-select: none;">
  6. </body>
  7. <script>
  8. /* (function(){
  9. document.getElementById("content").innerHTML='<object type="text/html" data="http://localhost:9999/"></object>';
  10. })();
  11. */
  12. const myRequest = new Request('http://127.0.0.1:9999/', {
  13. method: 'GET',
  14. headers: new Headers(),
  15. type: "arraybuffer",
  16. mode: 'cors',
  17. cache: 'default',
  18. });
  19. var source = new EventSource("http://127.0.0.1:9999/");
  20. source.onmessage = function (event) {
  21. console.log(event)
  22. var counter = event.data; // JSON.parse(event.data);
  23. document.getElementById("content").innerHTML = counter;
  24. }
  25. fetch(myRequest).then(response => {
  26. console.log(response)
  27. console.log(response.headers)
  28. const contentType = response.headers.get("content-type");
  29. if (contentType && contentType.indexOf("application/json") !== -1) {
  30. return response.json().then(data => {
  31. var obj = JSON.parse(str);
  32. console.log(obj)
  33. // Process your data as a JavaScript object
  34. });
  35. } if (contentType && contentType.indexOf("image/jpeg") !== -1) {
  36. console.log("Image received")
  37. return response.blob().then(data => {
  38. var reader = new FileReader();
  39. reader.readAsDataURL(blob);
  40. reader.onloadend = function() {
  41. var imageUrl = reader.result;
  42. var img = document.querySelector("#photo");
  43. img.src = imageUrl;
  44. }
  45. });
  46. } else if (contentType && contentType.indexOf("text/event-stream") !== -1) {
  47. return response.text().then(text => {
  48. console.log(text)
  49. var source = new EventSource("http://localhost:9999/");
  50. source.onmessage = function (event) {
  51. var response = event.data // JSON.parse(event.data);
  52. document.getElementById("content").innerHTML = counter;
  53. }
  54. // Process your text as a String
  55. });
  56. } else if (contentType && contentType.indexOf("text/html") !== -1) {
  57. return response.text().then(text => {
  58. console.log(text)
  59. var source = new EventSource("http://localhost:9999/");
  60. source.onmessage = function (event) {
  61. var response = event.data // JSON.parse(event.data);
  62. document.getElementById("content").innerHTML = counter;
  63. }
  64. // Process your text as a String
  65. });
  66. }
  67. });
  68. </script>
  69. </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:

  1. package main
  2. import (
  3. &quot;context&quot;
  4. &quot;fmt&quot;
  5. &quot;net/http&quot;
  6. &quot;os&quot;
  7. &quot;os/signal&quot;
  8. &quot;syscall&quot;
  9. _ &quot;github.com/mattn/go-sqlite3&quot;
  10. &quot;github.com/skip2/go-qrcode&quot;
  11. &quot;google.golang.org/protobuf/proto&quot;
  12. &quot;go.mau.fi/whatsmeow&quot;
  13. &quot;go.mau.fi/whatsmeow/store&quot;
  14. &quot;go.mau.fi/whatsmeow/store/sqlstore&quot;
  15. &quot;go.mau.fi/whatsmeow/types/events&quot;
  16. waLog &quot;go.mau.fi/whatsmeow/util/log&quot;
  17. )
  18. func eventHandler(evt interface{}) {
  19. switch v := evt.(type) {
  20. case *events.Message:
  21. fmt.Println(&quot;Received a message!&quot;, v.Message.GetConversation())
  22. }
  23. }
  24. func main() {
  25. passer := &amp;DataPasser{logs: make(chan string)}
  26. http.HandleFunc(&quot;/&quot;, passer.handleHello)
  27. go http.ListenAndServe(&quot;:9999&quot;, nil)
  28. store.DeviceProps.Os = proto.String(&quot;WhatsApp GO&quot;)
  29. dbLog := waLog.Stdout(&quot;Database&quot;, &quot;DEBUG&quot;, true)
  30. // Make sure you add appropriate DB connector imports, e.g. github.com/mattn/go-sqlite3 for SQLite
  31. container, err := sqlstore.New(&quot;sqlite3&quot;, &quot;file:datastore.db?_foreign_keys=on&quot;, dbLog)
  32. if err != nil {
  33. panic(err)
  34. }
  35. // If you want multiple sessions, remember their JIDs and use .GetDevice(jid) or .GetAllDevices() instead.
  36. deviceStore, err := container.GetFirstDevice()
  37. if err != nil {
  38. panic(err)
  39. }
  40. clientLog := waLog.Stdout(&quot;Client&quot;, &quot;DEBUG&quot;, true)
  41. client := whatsmeow.NewClient(deviceStore, clientLog)
  42. client.AddEventHandler(eventHandler)
  43. if client.Store.ID == nil {
  44. // No ID stored, new login
  45. qrChan, _ := client.GetQRChannel(context.Background())
  46. err = client.Connect()
  47. if err != nil {
  48. panic(err)
  49. }
  50. for evt := range qrChan {
  51. switch evt.Event {
  52. case &quot;success&quot;:
  53. {
  54. passer.logs &lt;- &quot;success&quot;
  55. fmt.Println(&quot;Login event: success&quot;)
  56. }
  57. case &quot;timeout&quot;:
  58. {
  59. passer.logs &lt;- &quot;timeout&quot;
  60. fmt.Println(&quot;Login event: timeout&quot;)
  61. }
  62. case &quot;code&quot;:
  63. {
  64. passer.logs &lt;- &quot;new code&quot;
  65. fmt.Println(&quot;new code recieved&quot;)
  66. img, err := qrcode.Encode(evt.Code, qrcode.Medium, 200) // evt.Code
  67. if err != nil {
  68. fmt.Println(&quot;error when write qrImage&quot;, err.Error())
  69. }
  70. passer.logs &lt;- string(img)
  71. }
  72. }
  73. }
  74. } else {
  75. // Already logged in, just connect
  76. passer.logs &lt;- &quot;Already logged&quot;
  77. fmt.Println(&quot;Already logged&quot;)
  78. err = client.Connect()
  79. if err != nil {
  80. panic(err)
  81. }
  82. }
  83. // Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
  84. c := make(chan os.Signal, 1)
  85. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  86. &lt;-c
  87. client.Disconnect()
  88. }

With the below api:

  1. package main
  2. import (
  3. &quot;bytes&quot;
  4. &quot;fmt&quot;
  5. &quot;log&quot;
  6. &quot;net/http&quot;
  7. &quot;strconv&quot;
  8. &quot;sync&quot;
  9. )
  10. var (
  11. mux sync.Mutex
  12. )
  13. type Result struct {
  14. ResultType, Result string
  15. }
  16. type DataPasser struct {
  17. logs chan string
  18. }
  19. func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
  20. setupCORS(&amp;w, r)
  21. w.Header().Set(&quot;Content-Type&quot;, &quot;text/event-stream&quot;)
  22. flusher, ok := w.(http.Flusher)
  23. if !ok {
  24. http.Error(w, &quot;Internal error&quot;, 500)
  25. return
  26. }
  27. flusher.Flush()
  28. done := r.Context().Done()
  29. defer fmt.Println(&quot;EXIT&quot;)
  30. for {
  31. select {
  32. case &lt;-done:
  33. // the client disconnected
  34. return
  35. case m := &lt;-p.logs:
  36. fmt.Println(m)
  37. 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; {
  38. if _, err := fmt.Fprintf(w, &quot;data: %s\n\n&quot;, m); err != nil {
  39. // Write to connection failed. Subsequent writes will probably fail.
  40. return
  41. }
  42. flusher.Flush()
  43. } else {
  44. mux.Lock()
  45. buffer := bytes.NewBuffer([]byte(m))
  46. /* img, _, err := image.Decode(buffer)
  47. if err != nil {
  48. fmt.Println(&quot;err: &quot;, err)
  49. }
  50. if err := jpeg.Encode(buffer, img, nil); err != nil {
  51. log.Println(&quot;unable to encode image.&quot;)
  52. } */
  53. w.Header().Set(&quot;Content-Type&quot;, &quot;image/jpeg&quot;)
  54. w.Header().Set(&quot;Content-Length&quot;, strconv.Itoa(len(buffer.Bytes())))
  55. if _, err := w.Write(buffer.Bytes()); err != nil {
  56. log.Println(&quot;unable to write image.&quot;)
  57. }
  58. mux.Unlock()
  59. flusher.Flush()
  60. }
  61. }
  62. }
  63. }
  64. func setupCORS(w *http.ResponseWriter, req *http.Request) {
  65. (*w).Header().Set(&quot;Cache-Control&quot;, &quot;no-cache&quot;)
  66. (*w).Header().Set(&quot;Connection&quot;, &quot;keep-alive&quot;)
  67. (*w).Header().Set(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;)
  68. (*w).Header().Set(&quot;Access-Control-Allow-Methods&quot;, &quot;POST, GET, OPTIONS, PUT, DELETE&quot;)
  69. (*w).Header().Set(&quot;Access-Control-Allow-Headers&quot;, &quot;Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization&quot;)
  70. }

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

  1. &lt;html&gt;
  2. &lt;head&gt;&lt;/head&gt;
  3. &lt;body&gt;
  4. note: &lt;span id=&quot;content&quot;&gt;&lt;/span&gt;&lt;br&gt;
  5. &lt;img id=&quot;photo&quot; style=&quot;display: block;-webkit-user-select: none;&quot;&gt;
  6. &lt;/body&gt;
  7. &lt;script&gt;
  8. /* (function(){
  9. 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;;
  10. })();
  11. */
  12. const myRequest = new Request(&#39;http://127.0.0.1:9999/&#39;, {
  13. method: &#39;GET&#39;,
  14. headers: new Headers(),
  15. type: &quot;arraybuffer&quot;,
  16. mode: &#39;cors&#39;,
  17. cache: &#39;default&#39;,
  18. });
  19. var source = new EventSource(&quot;http://127.0.0.1:9999/&quot;);
  20. source.onmessage = function (event) {
  21. console.log(event)
  22. var counter = event.data; // JSON.parse(event.data);
  23. document.getElementById(&quot;content&quot;).innerHTML = counter;
  24. }
  25. fetch(myRequest).then(response =&gt; {
  26. console.log(response)
  27. console.log(response.headers)
  28. const contentType = response.headers.get(&quot;content-type&quot;);
  29. if (contentType &amp;&amp; contentType.indexOf(&quot;application/json&quot;) !== -1) {
  30. return response.json().then(data =&gt; {
  31. var obj = JSON.parse(str);
  32. console.log(obj)
  33. // Process your data as a JavaScript object
  34. });
  35. } if (contentType &amp;&amp; contentType.indexOf(&quot;image/jpeg&quot;) !== -1) {
  36. console.log(&quot;Image received&quot;)
  37. return response.blob().then(data =&gt; {
  38. var reader = new FileReader();
  39. reader.readAsDataURL(blob);
  40. reader.onloadend = function() {
  41. var imageUrl = reader.result;
  42. var img = document.querySelector(&quot;#photo&quot;);
  43. img.src = imageUrl;
  44. }
  45. });
  46. } else if (contentType &amp;&amp; contentType.indexOf(&quot;text/event-stream&quot;) !== -1) {
  47. return response.text().then(text =&gt; {
  48. console.log(text)
  49. var source = new EventSource(&quot;http://localhost:9999/&quot;);
  50. source.onmessage = function (event) {
  51. var response = event.data // JSON.parse(event.data);
  52. document.getElementById(&quot;content&quot;).innerHTML = counter;
  53. }
  54. // Process your text as a String
  55. });
  56. } else if (contentType &amp;&amp; contentType.indexOf(&quot;text/html&quot;) !== -1) {
  57. return response.text().then(text =&gt; {
  58. console.log(text)
  59. var source = new EventSource(&quot;http://localhost:9999/&quot;);
  60. source.onmessage = function (event) {
  61. var response = event.data // JSON.parse(event.data);
  62. document.getElementById(&quot;content&quot;).innerHTML = counter;
  63. }
  64. // Process your text as a String
  65. });
  66. }
  67. });
  68. &lt;/script&gt;
  69. &lt;/html&gt;

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

将 QR 推送到客户端

Any help?

答案1

得分: 0

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

  1. // main.go
  2. package main
  3. import (
  4. "context"
  5. "fmt"
  6. "net/http"
  7. "os"
  8. "os/signal"
  9. "syscall"
  10. _ "github.com/mattn/go-sqlite3"
  11. "google.golang.org/protobuf/proto"
  12. "go.mau.fi/whatsmeow"
  13. "go.mau.fi/whatsmeow/store"
  14. "go.mau.fi/whatsmeow/store/sqlstore"
  15. "go.mau.fi/whatsmeow/types/events"
  16. waLog "go.mau.fi/whatsmeow/util/log"
  17. )
  18. func eventHandler(evt interface{}) {
  19. switch v := evt.(type) {
  20. case *events.Message:
  21. fmt.Println("Received a message!", v.Message.GetConversation())
  22. }
  23. }
  24. func main() {
  25. passer := &DataPasser{logs: make(chan string)}
  26. http.HandleFunc("/sse/dashboard", passer.handleHello)
  27. go http.ListenAndServe(":1234", nil)
  28. /*
  29. ticker := time.NewTicker(500 * time.Millisecond)
  30. defer ticker.Stop()
  31. done := make(chan bool)
  32. go func() {
  33. for {
  34. select {
  35. case <-done:
  36. return
  37. case <-ticker.C:
  38. // fmt.Println("Tick at", t)
  39. // passer.logs <- buffer.String()
  40. }
  41. }
  42. }()
  43. */
  44. store.DeviceProps.Os = proto.String("WhatsApp GO")
  45. dbLog := waLog.Stdout("Database", "DEBUG", true)
  46. // Make sure you add appropriate DB connector imports, e.g. github.com/mattn/go-sqlite3 for SQLite
  47. container, err := sqlstore.New("sqlite3", "file:datastore.db?_foreign_keys=on", dbLog)
  48. if err != nil {
  49. panic(err)
  50. }
  51. // If you want multiple sessions, remember their JIDs and use .GetDevice(jid) or .GetAllDevices() instead.
  52. deviceStore, err := container.GetFirstDevice()
  53. if err != nil {
  54. panic(err)
  55. }
  56. clientLog := waLog.Stdout("Client", "DEBUG", true)
  57. client := whatsmeow.NewClient(deviceStore, clientLog)
  58. client.AddEventHandler(eventHandler)
  59. if client.Store.ID == nil {
  60. // No ID stored, new login
  61. qrChan, _ := client.GetQRChannel(context.Background())
  62. err = client.Connect()
  63. if err != nil {
  64. panic(err)
  65. }
  66. for evt := range qrChan {
  67. switch evt.Event {
  68. case "success":
  69. {
  70. passer.logs <- "success"
  71. fmt.Println("Login event: success")
  72. }
  73. case "timeout":
  74. {
  75. passer.logs <- "timeout"
  76. fmt.Println("Login event: timeout")
  77. }
  78. case "code":
  79. {
  80. fmt.Println("new code recieved")
  81. fmt.Println(evt.Code)
  82. passer.logs <- evt.Code
  83. }
  84. }
  85. }
  86. } else {
  87. // Already logged in, just connect
  88. passer.logs <- "Already logged"
  89. fmt.Println("Already logged")
  90. err = client.Connect()
  91. if err != nil {
  92. panic(err)
  93. }
  94. }
  95. // Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
  96. c := make(chan os.Signal, 1)
  97. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  98. <-c
  99. client.Disconnect()
  100. }

  1. // api.go
  2. package main
  3. import (
  4. "fmt"
  5. "net/http"
  6. "sync"
  7. )
  8. var (
  9. mux sync.Mutex
  10. )
  11. type DataPasser struct {
  12. logs chan string
  13. }
  14. func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
  15. fmt.Println("from here")
  16. flusher, ok := w.(http.Flusher)
  17. if !ok {
  18. http.Error(w, "Internal error", 500)
  19. return
  20. }
  21. w.Header().Set("Content-Type", "text/event-stream")
  22. w.Header().Set("Cache-Control", "no-cache")
  23. w.Header().Set("Connection", "keep-alive")
  24. setupCORS(&w, r)
  25. for {
  26. select {
  27. case c := <-p.logs:
  28. fmt.Println("recieved")
  29. mux.Lock()
  30. //counter++
  31. //c := counter
  32. mux.Unlock()
  33. fmt.Fprintf(w, "data: %v\n\n", c)
  34. flusher.Flush()
  35. case <-r.Context().Done():
  36. fmt.Println("Connection closed")
  37. return
  38. }
  39. }
  40. }
  41. func setupCORS(w *http.ResponseWriter, req *http.Request) {
  42. (*w).Header().Set("Cache-Control", "no-cache")
  43. (*w).Header().Set("Access-Control-Allow-Origin", "*")
  44. (*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
  45. (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
  46. }

和客户端代码:

  1. <html lang="en">
  2. <head>
  3. <meta charset="utf-8">
  4. <meta name="viewport" content="width=device-width, initial-scale=1">
  5. <script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
  6. </head>
  7. <body>
  8. <h5>Server message/Code: <span id="message"></span></h5>
  9. <div id="qr"></div>
  10. <script>
  11. var source = new EventSource("http://localhost:1234/sse/dashboard");
  12. source.onmessage = function (event) {
  13. var message = event.data
  14. document.querySelector('#message').innerHTML = message;
  15. if (new String(message).valueOf() == "success" || new String(message).valueOf() == "timeout"
  16. || new String(message).valueOf() == "Already logged") {
  17. document.querySelector('#qr').innerHTML = "";
  18. } else {
  19. var qrcode = new QRCode("qr", {
  20. text: message,
  21. width: 128,
  22. height: 128,
  23. colorDark : "#000000",
  24. colorLight : "#ffffff",
  25. correctLevel : QRCode.CorrectLevel.M
  26. });
  27. }
  28. }
  29. /*
  30. var qrcode = new QRCode(
  31. "qr",
  32. [
  33. "BEGIN:VCARD",
  34. "VERSION:2.1",
  35. "N:Doe;John;;Dr;",
  36. "FN:Dr. John Doe",
  37. "EMAIL:johndoe@hotmail.com",
  38. "TEL;TYPE=cell:(123) 555-5832",
  39. "END:VCARD"
  40. ].join("\r\n")
  41. ); */
  42. </script>
  43. </body>
  44. </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:

  1. // main.go
  2. package main
  3. import (
  4. &quot;context&quot;
  5. &quot;fmt&quot;
  6. &quot;net/http&quot;
  7. &quot;os&quot;
  8. &quot;os/signal&quot;
  9. &quot;syscall&quot;
  10. _ &quot;github.com/mattn/go-sqlite3&quot;
  11. &quot;google.golang.org/protobuf/proto&quot;
  12. &quot;go.mau.fi/whatsmeow&quot;
  13. &quot;go.mau.fi/whatsmeow/store&quot;
  14. &quot;go.mau.fi/whatsmeow/store/sqlstore&quot;
  15. &quot;go.mau.fi/whatsmeow/types/events&quot;
  16. waLog &quot;go.mau.fi/whatsmeow/util/log&quot;
  17. )
  18. func eventHandler(evt interface{}) {
  19. switch v := evt.(type) {
  20. case *events.Message:
  21. fmt.Println(&quot;Received a message!&quot;, v.Message.GetConversation())
  22. }
  23. }
  24. func main() {
  25. passer := &amp;DataPasser{logs: make(chan string)}
  26. http.HandleFunc(&quot;/sse/dashboard&quot;, passer.handleHello)
  27. go http.ListenAndServe(&quot;:1234&quot;, nil)
  28. /*
  29. ticker := time.NewTicker(500 * time.Millisecond)
  30. defer ticker.Stop()
  31. done := make(chan bool)
  32. go func() {
  33. for {
  34. select {
  35. case &lt;-done:
  36. return
  37. case &lt;-ticker.C:
  38. // fmt.Println(&quot;Tick at&quot;, t)
  39. // passer.logs &lt;- buffer.String()
  40. }
  41. }
  42. }()
  43. */
  44. store.DeviceProps.Os = proto.String(&quot;WhatsApp GO&quot;)
  45. dbLog := waLog.Stdout(&quot;Database&quot;, &quot;DEBUG&quot;, true)
  46. // Make sure you add appropriate DB connector imports, e.g. github.com/mattn/go-sqlite3 for SQLite
  47. container, err := sqlstore.New(&quot;sqlite3&quot;, &quot;file:datastore.db?_foreign_keys=on&quot;, dbLog)
  48. if err != nil {
  49. panic(err)
  50. }
  51. // If you want multiple sessions, remember their JIDs and use .GetDevice(jid) or .GetAllDevices() instead.
  52. deviceStore, err := container.GetFirstDevice()
  53. if err != nil {
  54. panic(err)
  55. }
  56. clientLog := waLog.Stdout(&quot;Client&quot;, &quot;DEBUG&quot;, true)
  57. client := whatsmeow.NewClient(deviceStore, clientLog)
  58. client.AddEventHandler(eventHandler)
  59. if client.Store.ID == nil {
  60. // No ID stored, new login
  61. qrChan, _ := client.GetQRChannel(context.Background())
  62. err = client.Connect()
  63. if err != nil {
  64. panic(err)
  65. }
  66. for evt := range qrChan {
  67. switch evt.Event {
  68. case &quot;success&quot;:
  69. {
  70. passer.logs &lt;- &quot;success&quot;
  71. fmt.Println(&quot;Login event: success&quot;)
  72. }
  73. case &quot;timeout&quot;:
  74. {
  75. passer.logs &lt;- &quot;timeout&quot;
  76. fmt.Println(&quot;Login event: timeout&quot;)
  77. }
  78. case &quot;code&quot;:
  79. {
  80. fmt.Println(&quot;new code recieved&quot;)
  81. fmt.Println(evt.Code)
  82. passer.logs &lt;- evt.Code
  83. }
  84. }
  85. }
  86. } else {
  87. // Already logged in, just connect
  88. passer.logs &lt;- &quot;Already logged&quot;
  89. fmt.Println(&quot;Already logged&quot;)
  90. err = client.Connect()
  91. if err != nil {
  92. panic(err)
  93. }
  94. }
  95. // Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
  96. c := make(chan os.Signal, 1)
  97. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  98. &lt;-c
  99. client.Disconnect()
  100. }

And

  1. // api.go
  2. package main
  3. import (
  4. &quot;fmt&quot;
  5. &quot;net/http&quot;
  6. &quot;sync&quot;
  7. )
  8. var (
  9. mux sync.Mutex
  10. )
  11. type DataPasser struct {
  12. logs chan string
  13. }
  14. func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
  15. fmt.Println(&quot;from here&quot;)
  16. flusher, ok := w.(http.Flusher)
  17. if !ok {
  18. http.Error(w, &quot;Internal error&quot;, 500)
  19. return
  20. }
  21. w.Header().Set(&quot;Content-Type&quot;, &quot;text/event-stream&quot;)
  22. w.Header().Set(&quot;Cache-Control&quot;, &quot;no-cache&quot;)
  23. w.Header().Set(&quot;Connection&quot;, &quot;keep-alive&quot;)
  24. setupCORS(&amp;w, r)
  25. for {
  26. select {
  27. case c := &lt;-p.logs:
  28. fmt.Println(&quot;recieved&quot;)
  29. mux.Lock()
  30. //counter++
  31. //c := counter
  32. mux.Unlock()
  33. fmt.Fprintf(w, &quot;data: %v\n\n&quot;, c)
  34. flusher.Flush()
  35. case &lt;-r.Context().Done():
  36. fmt.Println(&quot;Connection closed&quot;)
  37. return
  38. }
  39. }
  40. }
  41. func setupCORS(w *http.ResponseWriter, req *http.Request) {
  42. (*w).Header().Set(&quot;Cache-Control&quot;, &quot;no-cache&quot;)
  43. (*w).Header().Set(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;)
  44. (*w).Header().Set(&quot;Access-Control-Allow-Methods&quot;, &quot;POST, GET, OPTIONS, PUT, DELETE&quot;)
  45. (*w).Header().Set(&quot;Access-Control-Allow-Headers&quot;, &quot;Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization&quot;)
  46. }

And the client side is:

  1. &lt;html lang=&quot;en&quot;&gt;
  2. &lt;head&gt;
  3. &lt;meta charset=&quot;utf-8&quot;&gt;
  4. &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
  5. &lt;script src=&quot;https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js&quot;&gt;&lt;/script&gt;
  6. &lt;/head&gt;
  7. &lt;body&gt;
  8. &lt;h5&gt;Server message/Code: &lt;span id=&quot;message&quot;&gt;&lt;/span&gt;&lt;/h5&gt;
  9. &lt;div id=&quot;qr&quot;&gt;&lt;/div&gt;
  10. &lt;script&gt;
  11. var source = new EventSource(&quot;http://localhost:1234/sse/dashboard&quot;);
  12. source.onmessage = function (event) {
  13. var message = event.data
  14. document.querySelector(&#39;#message&#39;).innerHTML = message;
  15. if (new String(message).valueOf() == &quot;success&quot; || new String(message).valueOf() == &quot;timeout&quot;
  16. || new String(message).valueOf() == &quot;Already logged&quot;) {
  17. document.querySelector(&#39;#qr&#39;).innerHTML = &quot;&quot;;
  18. } else {
  19. var qrcode = new QRCode(&quot;qr&quot;, {
  20. text: message,
  21. width: 128,
  22. height: 128,
  23. colorDark : &quot;#000000&quot;,
  24. colorLight : &quot;#ffffff&quot;,
  25. correctLevel : QRCode.CorrectLevel.M
  26. });
  27. }
  28. }
  29. /*
  30. var qrcode = new QRCode(
  31. &quot;qr&quot;,
  32. [
  33. &quot;BEGIN:VCARD&quot;,
  34. &quot;VERSION:2.1&quot;,
  35. &quot;N:Doe;John;;Dr;&quot;,
  36. &quot;FN:Dr. John Doe&quot;,
  37. &quot;EMAIL:johndoe@hotmail.com&quot;,
  38. &quot;TEL;TYPE=cell:(123) 555-5832&quot;,
  39. &quot;END:VCARD&quot;
  40. ].join(&quot;\r\n&quot;)
  41. ); */
  42. &lt;/script&gt;
  43. &lt;/body&gt;
  44. &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:

确定