purgeModal.go (4694B)
1 package streamModals 2 3 import ( 4 "bytes" 5 "dkforest/pkg/database" 6 "dkforest/pkg/utils" 7 "dkforest/pkg/web/handlers/interceptors/command" 8 "fmt" 9 "html/template" 10 "strconv" 11 "strings" 12 ) 13 14 const purgeModalName = "purge" 15 16 type PurgeModal struct { 17 StreamModal 18 } 19 20 func (m PurgeModal) Show(userID database.UserID, roomID database.RoomID, payload database.ChatMessageType) { 21 database.MsgPubSub.Pub(m.showTopic(purgeModalName, userID, roomID), payload) 22 } 23 24 func (m PurgeModal) Hide(userID database.UserID, roomID database.RoomID) { 25 database.MsgPubSub.Pub(m.hideTopic(purgeModalName, userID, roomID), database.ChatMessageType{}) 26 } 27 28 func NewPurgeModal(userID database.UserID, room database.ChatRoom) *PurgeModal { 29 m := &PurgeModal{StreamModal{name: purgeModalName, userID: userID, room: room}} 30 m.topics = append(m.topics, m.showTopic(purgeModalName, userID, room.ID), m.hideTopic(purgeModalName, userID, room.ID)) 31 return m 32 } 33 34 func (m *PurgeModal) Css() string { 35 return getPurgeModalCss() 36 } 37 38 func (m *PurgeModal) Handle(db *database.DkfDB, authUser database.IUserRenderMessage, topic, csrf string, msgTyp database.ChatMessageType, send func(string)) bool { 39 if topic == m.topics[0] { 40 send(getPurgeModalHTML(db, m.idx, m.room.Name, csrf, msgTyp)) 41 return true 42 43 } else if topic == m.topics[1] { 44 send(`<style>.purge-modal-` + strconv.Itoa(m.idx) + `{display:none;}</style>`) 45 m.idx++ 46 return true 47 } 48 49 return false 50 } 51 52 func getPurgeModalCss() string { 53 return strings.Join(strings.Split(` 54 .purge-modal { 55 display: block; 56 width: 400px; 57 left: calc(50% - 200px - (185px/2)); 58 height: 100px; 59 position: fixed; top: 0; 60 background-color: gray; z-index: 999; border-radius: 5px; 61 } 62 .purge-modal .header { position: absolute; top: 0; right: 0; } 63 .purge-modal .header .cancel { 64 border: 1px solid gray; 65 background-color: #ff7070; 66 color: #850000; 67 font-size: 18px; 68 height: 23px; 69 border: 1px solid #850000; 70 border-radius: 0 5px 0 5px; 71 cursor: pointer; 72 } 73 .purge-modal .header .cancel:hover { 74 background-color: #ff6767; 75 } 76 .purge-modal .wrapper { position: absolute; top: 25px; left: 10px; right: 10px; bottom: 30px; } 77 .purge-modal .wrapper textarea { width: 100%; height: 100%; color: #fff; background-color: rgba(79,79,79,1); border: 1px solid rgba(90,90,90,1); } 78 .purge-modal .controls { position: absolute; left: 10px; right: 10px; bottom: 5px; }`, "\n"), " ") 79 } 80 81 func getPurgeModalHTML(db *database.DkfDB, purgeModalIdx int, roomName, csrf string, msgTyp database.ChatMessageType) string { 82 htmlTmpl := `<div class="purge-modal purge-modal-{{ .PurgeModalIdx }}"> 83 <form method="post" target="iframe1" action="/api/v1/chat/top-bar/{{ .RoomName }}"> 84 <input type="hidden" name="csrf" value="{{ .CSRF }}" /> 85 <input type="hidden" name="sender" value="purgeModal" /> 86 <div class=wrapper> 87 <input type="text" name="username" placeholder="username" autocomplete="off" autocapitalize="none" /> 88 <select name="typ"> 89 <option value="all">All messages</option> 90 <option value="hb">HB messages</option> 91 </select> 92 <select name="delta"> 93 <option value="300">5 minutes</option> 94 <option value="3600" selected>1 hour</option> 95 <option value="21600">6 hour</option> 96 <option value="43200">12 hour</option> 97 <option value="86400">24 hour</option> 98 </select> 99 </div> 100 <div class="controls"> 101 <button type="submit">purge</button> 102 </div> 103 <div class="header"> 104 <button class="cancel" type="submit" name="btn_cancel" value="1">×</button> 105 </div> 106 </form> 107 </div>` 108 data := map[string]any{ 109 "CSRF": csrf, 110 "RoomName": roomName, 111 "PurgeModalIdx": purgeModalIdx, 112 } 113 var buf bytes.Buffer 114 _ = utils.Must(template.New("").Parse(htmlTmpl)).Execute(&buf, data) 115 return buf.String() 116 } 117 118 func (_ PurgeModal) InterceptMsg(cmd *command.Command) { 119 sender := cmd.C.Request().PostFormValue("sender") 120 btnCancel := cmd.C.Request().PostFormValue("btn_cancel") 121 delta := utils.DoParseInt64(cmd.C.Request().PostFormValue("delta")) 122 username := database.Username(cmd.C.Request().PostFormValue("username")) 123 typ := cmd.C.Request().PostFormValue("typ") 124 125 if !cmd.AuthUser.IsAdmin || sender != "purgeModal" { 126 return 127 } 128 129 PurgeModal{}.Hide(cmd.AuthUser.ID, cmd.Room.ID) 130 131 if btnCancel == "1" { 132 cmd.Err = command.ErrRedirect 133 return 134 } 135 136 user, err := cmd.DB.GetUserByUsername(username) 137 if err != nil { 138 cmd.Err = err 139 return 140 } 141 cmd.DB.NewAudit(*cmd.AuthUser, fmt.Sprintf("purge %s #%d", user.Username, user.ID)) 142 _ = cmd.DB.DeleteUserChatMessagesOpt(user.ID, typ == "hb", delta) 143 144 database.MsgPubSub.Pub(database.RefreshTopic, database.ChatMessageType{Typ: database.ForceRefresh}) 145 146 cmd.Err = command.NewErrSuccess(string(user.Username) + " purged") 147 return 148 }