In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-05 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "how to create messages in building an instant messaging application". In daily operations, I believe many people have doubts about how to create messages in building an instant messaging application. I have consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts about "how to create messages in building an instant messaging application". Next, please follow the editor to study!
First add these routes to the main () function.
Router.HandleFunc ("POST", "/ api/conversations/:conversationID/messages", requireJSON (guard (createMessage) router.HandleFunc ("GET", "/ api/conversations/:conversationID/messages", guard (getMessages)) router.HandleFunc ("POST", "/ api/conversations/:conversationID/read_messages", guard (readMessages))
The message enters the conversation, so the endpoint contains the conversation ID.
Create message
The endpoint handles the POST request for / api/conversations/ {conversationID} / messages, whose JSON body contains only the message content and returns the newly created message. It has two side effects: updating the conversation last_message_id and updating the participant messages_read_at.
Func createMessage (w http.ResponseWriter, r * http.Request) {var input struct {Content string `json: "content" `} defer r.Body.Close () if err: = json.NewDecoder (r.Body) .Decode (& input) Err! = nil {http.Error (w, err.Error (), http.StatusBadRequest) return} errs: = make (map [string] string) input.Content = removeSpaces (input.Content) if input.Content = "" {errs ["content"] = "Message content required"} else if len ([] rune (input.Content)) > 480 {errs ["content"] = "Message too long. 480 max "} if len (errs)! = 0 {respond (w, Errors {errs}, http.StatusUnprocessableEntity) return} ctx: = r.Context () authUserID: = ctx.Value (keyAuthUserID). (string) conversationID: = way.Param (ctx," conversationID ") tx, err: = db.BeginTx (ctx, nil) if err! = nil {respondError (w, fmt.Errorf (" could not begin tx:% v ", err) return} () isParticipant, err: = queryParticipantExistance (ctx, tx, tx) ConversationID) if err! = nil {respondError (w, fmt.Errorf ("could not query participant existance:% v", err)) return} if! isParticipant {http.Error (w, "Conversation not found", http.StatusNotFound) return} var message Messageif err: = tx.QueryRowContext (ctx, `INSERT INTO messages (content, user_id, conversation_id) VALUES ($1, $2, $3) RETURNING id, created_ at`, input.Content, authUserID, conversationID). Scan (& message.ID,&message.CreatedAt,) Err! = nil {respondError (w, fmt.Errorf ("could not insert message:% v", err)) return} if _, err: = tx.ExecContext (ctx, `UPDATE conversations SET last_message_id = $1WHERE id = $2`, message.ID, conversationID); err! = nil {respondError (w, fmt.Errorf ("could not update conversation last message ID:% v", err)) return} if err = tx.Commit () Err! = nil {respondError (w, fmt.Errorf ("could not commit tx to create a message:% v", err)) return} go func () {if err = updateMessagesReadAt (nil, authUserID, conversationID); err! = nil {log.Printf ("could not update messages read at:% v\ n", err)} () message.Content = input.Contentmessage.UserID = authUserIDmessage.ConversationID = conversationID// TODO: notify about new message.message.Mine = true respond (w, message, http.StatusCreated)}
First, it decodes the request body into a structure that contains the content of the message. It then verifies that the content is not empty and is less than 480 characters.
Var rxSpaces = regexp.MustCompile ("\\ s +") func removeSpaces (s string) string {if s = = "" {return s} lines: = make ([] string, 0) for _, line: = range strings.Split (s, "\ n") {line = rxSpaces.ReplaceAllLiteralString (line, ") line = strings.TrimSpace (line) if line! =" {lines = append (lines, line)} return strings.Join (lines, "\ n")}
This is a function that removes spaces. It iterates through each line, removes more than two consecutive spaces, and then returns non-blank lines.
After verification, it will start a SQL transaction. First, it queries whether the participants in the conversation exist.
Func queryParticipantExistance (ctx context.Context, tx * sql.Tx, userID, conversationID string) (bool, error) {if ctx = = nil {ctx = context.Background ()} var exists boolif err: = tx.QueryRowContext (ctx, `SELECT EXISTS (SELECT 1 FROM participantsWHERE user_id = $1 AND conversation_id = $2) `, userID, conversationID). Scan (& exists); err! = nil {return false, err} return exists, nil}
I extract it into a function because it can be reused later.
If the user is not a conversation participant, we will return a 404 NOT Found error.
It then inserts the message and updates the conversation last_message_id. From then on, last_message_id cannot be NULL because we are not allowed to delete messages.
Next, commit the transaction and update the participant messages_read_at in goroutine.
Func updateMessagesReadAt (ctx context.Context, userID, conversationID string) error {if ctx = = nil {ctx = context.Background ()} if _, err: = db.ExecContext (ctx, `UPDATE participants SET messages_read_at = now () WHERE user_id = $1 AND conversation_id = $2`, userID, conversationID); err! = nil {return err} return nil}
We must let you know before we reply to the new message. This is the real-time section we're going to write in the next article, so I left a comment there.
Get the message
This endpoint handles GET requests to / api/conversations/ {conversationID} / messages. It responds with an JSON array containing all the messages in the session. It also has the side effect of updating the participant messages_read_at.
Func getMessages (w http.ResponseWriter, r * http.Request) {ctx: = r.Context () authUserID: = ctx.Value (keyAuthUserID). (string) conversationID: = way.Param (ctx, "conversationID") tx, err: = db.BeginTx (ctx, & sql.TxOptions {ReadOnly: true}) if err! = nil {respondError (w, fmt.Errorf ("could not begin tx:% v", err)) return} defer tx.Rollback () isParticipant, err: = queryParticipantExistance (ctx, tx, authUserID) ConversationID) if err! = nil {respondError (w, fmt.Errorf ("could not query participant existance:% v", err)) return} if! isParticipant {http.Error (w, "Conversation not found", http.StatusNotFound) return} rows, err: = tx.QueryContext (ctx, `SELECTid,content,created_at,user_id = $1 AS mineFROM messagesWHERE messages.conversation_id = $2ORDER BY messages.created_at DESC`, authUserID, conversationID) if err! = nil {respondError (w, fmt.Errorf ("could not query messages:% v") Err)) return} defer rows.Close () messages: = make ([] Message, 0) for rows.Next () {var message Messageif err = rows.Scan (& message.ID,&message.Content,&message.CreatedAt,&message.Mine,) Err! = nil {respondError (w, fmt.Errorf ("could not scan message:% v", err)) return} messages = append (messages, message)} if err = rows.Err (); err! = nil {respondError (w, fmt.Errorf ("could not iterate over messages:% v", err)) return} if err = tx.Commit () Err! = nil {respondError (w, fmt.Errorf ("could not commit tx to get messages:% v", err)) return} go func () {if err = updateMessagesReadAt (nil, authUserID, conversationID); err! = nil {log.Printf ("could not update messages read at:% v\ n", err)} () respond (w, messages, http.StatusOK)}
First, it starts a SQL transaction in read-only mode. Check whether the participant exists and query all messages. In each message, we use the currently authenticated user ID to see if the user owns the message (mine). It then commits the transaction, updates the participant messages_read_at in goroutine and responds with a message.
Read message
This endpoint handles POST requests for / api/conversations/ {conversationID} / read_messages. There is no request or response subject. At the front end, we make this request every time a new message arrives at the real-time stream.
Func readMessages (w http.ResponseWriter, r * http.Request) {ctx: = r.Context () authUserID: = ctx.Value (keyAuthUserID). (string) conversationID: = way.Param (ctx, "conversationID") if err: = updateMessagesReadAt (ctx, authUserID, conversationID); err! = nil {respondError (w, fmt.Errorf ("could not update messages read at:% v", err) return} w.WriteHeader (http.StatusNoContent)}
It uses the same function as updating the participant messages_read_at.
At this point, the study of "how to create messages in building an instant messaging application" is over. I hope to be able to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.