dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

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 }