commit d95504f768aa194c4f096f1426a88ec460150afb
parent baa57a927fa27ae1435ed334bf0bd4713b8cba6d
Author: n0tr1v <n0tr1v@protonmail.com>
Date: Sat, 20 May 2023 04:36:56 -0700
quicktemplate
Diffstat:
5 files changed, 1891 insertions(+), 1 deletion(-)
diff --git a/go.mod b/go.mod
@@ -59,6 +59,7 @@ require (
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.1.0 // indirect
+ github.com/valyala/quicktemplate v1.7.0 // indirect
golang.org/x/sys v0.6.0 // indirect
gopkg.in/gorp.v1 v1.7.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
diff --git a/go.sum b/go.sum
@@ -29,6 +29,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
@@ -142,6 +144,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -213,6 +216,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -394,9 +399,13 @@ github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
+github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM=
+github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
@@ -424,6 +433,7 @@ golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -457,6 +467,7 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -492,6 +503,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/pkg/web/handlers/api/v1/handlers.go b/pkg/web/handlers/api/v1/handlers.go
@@ -16,7 +16,9 @@ import (
"fmt"
"github.com/labstack/echo"
"github.com/sirupsen/logrus"
+ qt "github.com/valyala/quicktemplate"
"golang.org/x/net/websocket"
+ "io"
"net/http"
"net/url"
"regexp"
@@ -201,9 +203,28 @@ func chatMessages(c echo.Context) (status int, data chatMessagesData) {
return http.StatusOK, data
}
+func writeunesc(iow io.Writer, s string) {
+ qw := qt.AcquireWriter(iow)
+ streamunesc(qw, s)
+ qt.ReleaseWriter(qw)
+}
+
+func unesc(s string) string {
+ qb := qt.AcquireByteBuffer()
+ writeunesc(qb, s)
+ qs := string(qb.B)
+ qt.ReleaseByteBuffer(qb)
+ return qs
+}
+
+func streamunesc(qw *qt.Writer, s string) {
+ qw.N().S(s)
+}
+
// ChatMessagesHandler room messages iframe handler
// The chat messages iframe use this endpoint to get the messages for a room.
func ChatMessagesHandler(c echo.Context) error {
+ authUser := c.Get("authUser").(*database.User)
status, data := chatMessages(c)
if status != http.StatusOK {
return c.NoContent(status)
@@ -217,7 +238,10 @@ func ChatMessagesHandler(c echo.Context) error {
}
return c.JSON(http.StatusOK, data)
}
- return c.Render(http.StatusOK, "chat-messages", data)
+ version := config.Global.GetVersion().Original()
+ csrf, _ := c.Get("csrf").(string)
+ return c.HTML(http.StatusOK, Messages(version, csrf, config.NullUsername, authUser, data))
+ //return c.Render(http.StatusOK, "chat-messages", data)
}
func ChatMessagesWSHandler(c echo.Context) error {
diff --git a/pkg/web/handlers/api/v1/messages.qtpl b/pkg/web/handlers/api/v1/messages.qtpl
@@ -0,0 +1,431 @@
+{% import "dkforest/pkg/database" %}
+{% import "dkforest/pkg/managers" %}
+{% import humanize "github.com/dustin/go-humanize" %}
+
+{% func Messages(VERSION, CSRF, NullUsername string, AuthUser *database.User, Data chatMessagesData) %}
+
+<html lang="en">
+ <head>
+ <title></title>
+ {% if !Data.PreventRefresh && !Data.ForceManualRefresh %}<meta http-equiv="refresh" content="{%dl AuthUser.RefreshRate %}">{% endif %}
+ {% if AuthUser.CollectMetadata %}<link rel="stylesheet" type="text/css" href="/public/css/meta.css?v={%s VERSION %}" />{% endif %}
+
+ <style>
+ /* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+ */
+ html, body, div, span, applet, object, iframe,
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+ a, abbr, acronym, address, big, cite, code,
+ del, dfn, em, img, ins, kbd, q, s, samp,
+ small, strike, strong, sub, sup, tt, var,
+ b, u, i, center,
+ dl, dt, dd, ol, ul, li,
+ fieldset, form, label, legend,
+ table, caption, tbody, tfoot, thead, tr, th, td,
+ article, aside, canvas, details, embed,
+ figure, figcaption, footer, header, hgroup,
+ menu, nav, output, ruby, section, summary,
+ time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+ }
+ /* HTML5 display-role reset for older browsers */
+ article, aside, details, figcaption, figure,
+ footer, header, hgroup, menu, nav, section {
+ display: block;
+ }
+ body {
+ line-height: 1;
+ }
+ ol, ul {
+ list-style: none;
+ }
+ blockquote, q {
+ quotes: none;
+ }
+ blockquote:before, blockquote:after,
+ q:before, q:after {
+ content: '';
+ content: none;
+ }
+ table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+ /* --- end --- */
+
+
+ i { font-style: italic; }
+
+ /* Remove button padding in FF */
+ button::-moz-focus-inner {
+ border:0;
+ padding:0;
+ }
+
+ body { font-family: Lato,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; }
+ a { color: #00bc8c; text-decoration: none; }
+ a:hover { color: #007053; text-decoration: underline; }
+ .unread_room { color: #2392da; text-decoration: none; }
+ .unread_room:hover { color: #004970; text-decoration: underline; }
+ .emoji {
+ font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;
+ font-size: 17px;
+ }
+ .mod-btn {
+ width: 16px; height: 16px;
+ margin: 0; padding: 0;
+ border: 1px solid gray;
+ display: inline;
+ text-align: center;
+ vertical-align: middle;
+ user-select: none;
+ background-color: #444;
+ color: #ea2a2a;
+ -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.25);
+ -moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.25);
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ }
+ .mod-btn:hover {
+ background-color: #222;
+ }
+ .delete_msg_btn {
+ font-size: 15px;
+ line-height: 1;
+ }
+ .delete_msg_btn::after { content: "×"; }
+ .hb_btn {
+ font-size: 10px;
+ line-height: 1.4;
+ }
+ .hb_btn::after { content: "hb"; }
+ .k_btn {
+ font-size: 10px;
+ line-height: 1.4;
+ }
+ .k_btn::after { content: "k"; }
+ #manualrefresh {
+ {% if !Data.ForceManualRefresh %}
+ top: -200%;
+ animation: timeout_messages {%dl Data.ManualRefreshTimeout %}s forwards;
+ {% endif %}
+ color: #bf2718;
+ display: block;
+ position: fixed;
+ text-align: center;
+ left: calc(50% - 200px);
+ width: 400px;
+ z-index: 2;
+ background-color: #500000;
+ border: 2px solid #ff0000;
+ }
+ @keyframes timeout_messages {
+ 0% { top: -200%; }
+ 99% { top: -200%; }
+ 100% { top: 0; }
+ }
+ .date { color: #999; font-family: 'Courier New', Courier, monospace; font-size: 14px; }
+ .date-link:hover { color: #999; text-decoration: underline; }
+ .sysmsg { color: #fff; font-family: 'Courier New', Courier, monospace; font-size: 14px; }
+ small { font-size: 80%; font-weight: 400; }
+ .msg { padding: 3px 0 3px 8px; border-bottom: 1px solid #444; color: #888; position: relative; }
+ .msg p:first-of-type { display: inline; }
+ strong { font-weight: bold; }
+ em { font-style: italic; }
+ pre { border: 1px solid #2b442b; padding: 2px; margin: 2px 0; max-height: 300px; overflow: auto; background-color: rgba(39,40,34,0.6) !important;
+ font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; }
+ code { border: 1px solid #2b442b; color: #f92672; padding: 0 2px; margin: 0px 0; background-color: rgba(39,40,34,0.6) !important; }
+ .censored { background-color: black; color: black; padding: 0 3px; }
+ .censored:hover { background-color: black; color: white; }
+ ul { list-style-type: disc; margin: 0 0 0 15px; }
+ * {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+ .afk-indicator { color: #ff9a27; }
+ .spacer16 { display: inline-block; width: 16px; }
+ .spacer36 { display: inline-block; width: 36px; }
+ .spacer56 { display: inline-block; width: 56px; }
+ .d-inline { display: inline; }
+ .o-wrap { overflow-wrap: break-word; }
+ .f-def-clr { color: #888; }
+ .f-orange-clr { color: orange; }
+ .f-white-clr, .f-white-clr:hover { color: white; }
+ .line-through { text-decoration: line-through; }
+ .hb-row { background-color: rgba(0, 0, 0, 0.7); opacity: {%f AuthUser.GetHellbanOpacityF64() %}; }
+ .own-highlight { background-color: rgba(255,241,176,0.05); }
+ .read-marker { border-top: {%dl AuthUser.ChatReadMarkerSize %}px solid {%s AuthUser.ChatReadMarkerColor %}; }
+ #msgs { {% if !AuthUser.HideRightColumn %}width: calc(100% - 170px); float: left; {% endif %}line-height: 1.2; }
+ #no-msg { padding-left: 10px; color: #ddd; }
+ #rgt-pane { width: 150px; height: 100%; float: left; margin-left: 20px; position: fixed; right: 0; overflow-y: auto; line-height: 1.15; }
+ .rgt-title { font-weight: bolder; color: #ced4da; }
+ .mb-20px { margin-bottom: 20px; }
+ .mb-30px { margin-bottom: 30px; }
+ .mt-5px { margin-top: 5px; }
+ .mt-10px { margin-top: 10px; }
+ .notif, .notif:hover { color: #e74c3c; }
+ #msg-err { background-color: #8f2d2d; color: #ffffff; padding: 1px 5px 2px 5px; display: block; text-decoration: none; }
+ </style>
+ </head>
+ <body>
+
+ {% if Data.ForceManualRefresh %}
+ <div id="manualrefresh">
+ <h4>Manual refresh required</h4>
+ <form method="get" action="/chat/{%s Data.RoomName %}" target="_top">
+ <input type="submit" value="Reload" />
+ </form>
+ </div>
+ {% elseif !Data.PreventRefresh %}
+ <div id="manualrefresh">
+ <h4>Manual refresh required</h4>
+ <form method="get">
+ <input type="submit" value="Reload" />
+ </form>
+ </div>
+ {% endif %}
+
+ {% if Data.Error != "" %}
+ <a href="/api/v1/chat/messages/{%s Data.RoomName %}" id="msg-err">× {%s Data.Error %}</a>
+ {% endif %}
+
+ {% if Data.PmSound || Data.TaggedSound %}
+ <audio src="/public/mp3/sound5.mp3" autoplay></audio>
+ {% elseif Data.NewMessageSound %}
+ <audio src="/public/mp3/sound6.mp3" autoplay></audio>
+ {% endif %}
+
+ <div id="msgs">
+ {% code
+ baseTopBarURL := "/api/v1/chat/top-bar/" + Data.RoomName
+ readMarkerRendered := false
+ isFirstMsg := true
+ %}
+ {% for idx, e := range Data.Messages %}
+ {% if e.UserCanSee(*AuthUser) %}
+ <div id="msgid-{%s e.UUID %}" class="msg
+ {% if (e.User.IsHellbanned || e.IsHellbanned) && AuthUser.DisplayHellbanned %} hb-row
+ {% elseif AuthUser.ID == e.User.ID && AuthUser.HighlightOwnMessages %} own-highlight{% endif %}
+ {% if AuthUser.ChatReadMarkerEnabled && e.CreatedAt.Before(Data.ReadMarker.ReadAt) && !readMarkerRendered %}
+ {% if idx > 0 %} read-marker{% endif %}
+ {% code
+ readMarkerRendered = true
+ %}
+ {% endif %}
+ ">
+ {% if e.UserCanDelete(*AuthUser) %}
+ {% if !e.TooOldToDelete() %}
+ {% if AuthUser.DisplayDeleteButton %}
+ <form method="post" action="/api/v1/chat/messages/delete/{%s e.UUID %}" class="d-inline">
+ <input type="hidden" name="csrf" value="{%s CSRF %}" />
+ <button class="mod-btn delete_msg_btn" title="delete"></button>
+ </form>
+ {% endif %}
+ {% elseif (AuthUser.IsModerator() && e.TooOldToDelete() && e.UserID != AuthUser.ID) || AuthUser.IsAdmin || (e.Room.OwnerUserID != nil && *e.Room.OwnerUserID == AuthUser.ID) %}
+ {% if AuthUser.DisplayDeleteButton %}
+ <form method="post" action="/api/v1/chat/messages/delete/{%s e.UUID %}" class="d-inline">
+ <input type="hidden" name="csrf" value="{%s CSRF %}" />
+ <button class="mod-btn delete_msg_btn f-orange-clr" title="delete"></button>
+ </form>
+ {% endif %}
+ {% elseif AuthUser.IsModerator() %}
+ {% if AuthUser.DisplayDeleteButton %}
+ <div class="spacer16"></div>
+ {% endif %}
+ {% else %}
+ {% if AuthUser.DisplayDeleteButton %}
+ <div class="spacer16"></div>
+ {% endif %}
+ {% endif %}
+ {% if AuthUser.IsModerator() %}
+ {% if e.UserID != AuthUser.ID %}
+ {% if AuthUser.DisplayHellbanButton %}
+ {% if e.User.Username == NullUsername %}
+ <div class="spacer16"></div>
+ {% else %}
+ {% if e.User.IsHellbanned %}
+ <form method="post" action="/api/v1/users/{%s e.UserID.String() %}/unhellban" class="d-inline">
+ <input type="hidden" name="csrf" value="{%s CSRF %}" />
+ <button class="mod-btn hb_btn f-orange-clr line-through" title="unhellban"></button>
+ </form>
+ {% else %}
+ <form method="post" action="/api/v1/users/{%s e.UserID.String() %}/hellban" class="d-inline">
+ <input type="hidden" name="csrf" value="{%s CSRF %}" />
+ <button class="mod-btn hb_btn f-orange-clr" title="hellban"></button>
+ </form>
+ {% endif %}
+ {% endif %}
+ {% endif %}
+ {% if AuthUser.DisplayKickButton %}
+ <form method="post" action="/api/v1/users/{%s e.UserID.String() %}/kick" class="d-inline">
+ <input type="hidden" name="csrf" value="{%s CSRF %}" />
+ <button class="mod-btn k_btn f-orange-clr" title="kick"></button>
+ </form>
+ {% endif %}
+ {% else %}
+ {% if AuthUser.DisplayKickButton && AuthUser.DisplayHellbanButton %}
+ <div class="spacer36"></div>
+ {% elseif AuthUser.DisplayKickButton || AuthUser.DisplayHellbanButton %}
+ <div class="spacer16"></div>
+ {% endif %}
+ {% endif %}
+ {%- endif -%}
+ {%- else -%}
+ {%- if Data.NbButtons == 3 -%}
+ <div class="spacer56"></div>
+ {%- elseif Data.NbButtons == 2 -%}
+ <div class="spacer36"></div>
+ {%- elseif Data.NbButtons == 1 -%}
+ <div class="spacer16"></div>
+ {%- endif -%}
+ {%- endif -%}
+ {%- if Data.DateFormat != "" -%}
+ <a href="{%s baseTopBarURL %}?quote={%s e.UUID %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="date date-link" title="{%s e.CreatedAt.Format("01-02 15:04:05") %}{% if isFirstMsg %} ({%s humanize.Time(e.CreatedAt) %}){% endif %}">{%s e.CreatedAt.Format(Data.DateFormat) %}</a>
+ {% code isFirstMsg = false %}
+ {%- endif -%}
+ <a href="/u/{%s e.GetProfile(AuthUser) %}" target="_blank" class="f-def-clr">-</a>
+ {%- if e.System -%}
+ <span class="sysmsg">{%= unesc(e.Message) %}</span>
+ {%- else -%}
+ {%- if e.Moderators -%}<span class="sysmsg">[<a href="{%s baseTopBarURL %}?m=1{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="sysmsg f-white-clr">M</a>]</span> {%- endif -%}
+ {%- if e.GroupID != nil -%}<span class="sysmsg">[<a href="{%s baseTopBarURL %}?g={%s e.Group.Name %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="sysmsg f-white-clr">{%s e.Group.Name %}</a>]</span> {%- endif -%}
+ {%- if e.ToUserID != nil -%}
+ [{%-= fromUsername(AuthUser, Data, e, baseTopBarURL) -%}
+ →
+ {%- if e.ToUser.ID == AuthUser.ID -%}<span {%= unesc(e.ToUser.GenerateChatStyle()) %}>{%s e.ToUser.Username %}</span>{%- else -%}<a {%= unesc(e.ToUser.GenerateChatStyle()) %} href="{%s baseTopBarURL %}?pm={%s e.ToUser.Username %}{%s Data.TopBarQueryParams %}" target="iframe1">{%s e.ToUser.Username %}</a>{%- endif -%}] -
+ {%- else -%}
+ {%-= fromUsername(AuthUser, Data, e, baseTopBarURL) -%}
+ {%- if !e.IsMe() -%}
+ {%- if AuthUser.CanSeeHB() && (e.IsHellbanned || e.User.IsHellbanned) && (e.ToUserID == nil) -%}
+ <a href="{%s baseTopBarURL %}?hbm=1{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="f-def-clr">-</a>
+ {%- else -%}
+ -
+ {%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ <span {%= unesc(e.User.GenerateChatStyle()) %}><span class="o-wrap">{%s= unesc(e.MsgToDisplay()) %}</span></span>
+ {%- endif -%}
+ </div>
+ {%- endif -%}
+ {% endfor %}
+ {% if len(Data.Messages) == 0 %}
+ <div id="no-msg"><em>No message yet</em></div>
+ {% endif %}
+ </div>
+
+ {% if !AuthUser.HideRightColumn %}
+ <div id="rgt-pane">
+ <div class="mb-20px">
+ <div class="rgt-title">Inbox (<a href="/settings/inbox" target="_top"{% if Data.InboxCount > 0 %}class="notif"{% endif %}>{%dl Data.InboxCount %}</a>)</div>
+ </div>
+ <div class="mb-20px">
+ <div class="rgt-title">Rooms:</div>
+ {% for _, e := range Data.OfficialRooms %}
+ {% if e.Name == "club" %}
+ {% if AuthUser.IsClubMember %}
+ <div><a href="/chat/club" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#club</a></div>
+ {% endif %}
+ {% elseif e.Name == "moderators" %}
+ {% if AuthUser.IsModerator() %}
+ <div><a href="/chat/moderators" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#moderators</a></div>
+ {% endif %}
+ {% else %}
+ <div><a href="/chat/{%s e.Name %}" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#{%s e.Name %}</a></div>
+ {% endif %}
+ {% endfor %}
+ {% if len(Data.SubscribedRooms) > 0 %}
+ <div class="mt-10px"></div>
+ {% for _, e := range Data.SubscribedRooms %}
+ <div><a href="/chat/{%s e.Name %}" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#{%s e.Name %}</a></div>
+ {% endfor %}
+ {% endif %}
+ <div class="mt-5px"><a href="/rooms" target="_top">[...]</a></div>
+ </div>
+ <div class="mb-20px">
+ <div class="rgt-title">In this room:</div>
+ {% for _, e := range Data.Members %}
+ {%= Member(AuthUser, Data, e) %}
+ {% endfor %}
+ </div>
+ {% if Data.VisibleMemberInChat || AuthUser.DisplayHellbanned %}
+ <div class="mb-30px">
+ {% if len(Data.MembersInChat) > 0 %}
+ <div class="rgt-title">In other rooms:</div>
+ {% for _, e := range Data.MembersInChat %}
+ {%= Member(AuthUser, Data, e) %}
+ {% endfor %}
+ {% endif %}
+ </div>
+ {% endif %}
+ </div>
+ {% endif %}
+ {% if AuthUser.CollectMetadata %}
+ <div class="div_1"></div>
+ <div class="div_2"></div>
+ <div class="div_f0">a</div>
+ {% endif %}
+ </body>
+</html>
+{% endfunc %}
+
+
+
+{% func Member(AuthUser *database.User, Data chatMessagesData, El managers.UserInfo) %}
+ {% code baseTopBarURL := "/api/v1/chat/top-bar/" + Data.RoomName %}
+ {% if El.Username == AuthUser.Username %}
+ <div>
+ <span style="color: {%s El.Color %};">{%s El.Username %}</span>
+ {% if El.AfkIndicatorEnabled %}
+ <small class="afk-indicator">afk</small>
+ {% endif %}
+ </div>
+ {% else %}
+ {% if !El.IsHellbanned || AuthUser.ID == El.UserID || (El.IsHellbanned && AuthUser.IsHellbanned) || AuthUser.DisplayHellbanned %}
+ <div>
+ {% code tagType := "tag" %}
+ {% if AuthUser.CanSeeHB() && El.IsHellbanned %}
+ {% code tagType = "htag" %}
+ {% endif %}
+ {% stripspace %}
+ <a href="{%s baseTopBarURL %}?{%s tagType %}={%s El.Username %}{%= unesc(Data.TopBarQueryParams) %}"
+ target="iframe1"
+ {% if El.IsHellbanned && AuthUser.DisplayHellbanned %}class="hb-row"{% endif %}
+ style="color: {%s El.Color %};">{%s string(El.Username[0]) %}</a>
+ <a href="{%s baseTopBarURL %}?pm={%s El.Username %}{%= unesc(Data.TopBarQueryParams) %}"
+ target="iframe1"
+ {% if El.IsHellbanned && AuthUser.DisplayHellbanned %}class="hb-row"{% endif %}
+ style="color: {%s El.Color %};">{%s string(El.Username[1 : len(El.Username)-1]) %}</a>
+ <a href="/u/{%s El.Username %}"
+ rel="noopener noreferrer" target="_blank"
+ {% if El.IsHellbanned && AuthUser.DisplayHellbanned %}class="hb-row"{% endif %}
+ style="color: {%s El.Color %};">{%s string(El.Username[len(El.Username)-1]) %}</a>
+ {% endstripspace %}
+ {% if El.AfkIndicatorEnabled %}
+ <small class="afk-indicator">afk</small>
+ {% endif %}
+ </div>
+ {% endif %}
+ {% endif %}
+{% endfunc %}
+
+
+{%- func fromUsername(AuthUser *database.User, Data chatMessagesData, El database.ChatMessage, baseTopBarURL string) -%}
+ {%- code tagType := "tag" -%}
+ {%- if El.ToUserID != nil -%}
+ {%- code tagType = "pm" -%}
+ {%- elseif AuthUser.CanSeeHB() && (El.IsHellbanned || El.User.IsHellbanned) -%}
+ {%- code tagType = "htag" -%}
+ {%- elseif AuthUser.IsModerator() && El.Moderators -%}
+ {%- code tagType = "mtag" -%}
+ {%- endif -%}
+ {%- if El.User.ID == AuthUser.ID -%}
+ {%- if El.CanBeEdited() -%}<a {%= unesc(El.User.GenerateChatStyle()) %} href="{%s baseTopBarURL %}?e={%s El.CreatedAt.Format("15:04:05") %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1">{%s El.User.Username %}</a>{%- else -%}<span {%= unesc(El.User.GenerateChatStyle()) %}>{%s El.User.Username %}</span>{%- endif -%}
+ {%- else -%}<a {%= unesc(El.User.GenerateChatStyle()) %} href="{%s baseTopBarURL %}?{%s tagType %}={%s El.User.Username %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1">{%s El.User.Username %}</a>{%- endif -%}
+{%- endfunc -%}
diff --git a/pkg/web/handlers/api/v1/messages.qtpl.go b/pkg/web/handlers/api/v1/messages.qtpl.go
@@ -0,0 +1,1421 @@
+// Code generated by qtc from "messages.qtpl". DO NOT EDIT.
+// See https://github.com/valyala/quicktemplate for details.
+
+//line messages.qtpl:1
+package v1
+
+//line messages.qtpl:1
+import "dkforest/pkg/database"
+
+//line messages.qtpl:2
+import "dkforest/pkg/managers"
+
+//line messages.qtpl:3
+import humanize "github.com/dustin/go-humanize"
+
+//line messages.qtpl:5
+import (
+ qtio422016 "io"
+
+ qt422016 "github.com/valyala/quicktemplate"
+)
+
+//line messages.qtpl:5
+var (
+ _ = qtio422016.Copy
+ _ = qt422016.AcquireByteBuffer
+)
+
+//line messages.qtpl:5
+func StreamMessages(qw422016 *qt422016.Writer, VERSION, CSRF, NullUsername string, AuthUser *database.User, Data chatMessagesData) {
+//line messages.qtpl:5
+ qw422016.N().S(`
+
+<html lang="en">
+ <head>
+ <title></title>
+ `)
+//line messages.qtpl:10
+ if !Data.PreventRefresh && !Data.ForceManualRefresh {
+//line messages.qtpl:10
+ qw422016.N().S(`<meta http-equiv="refresh" content="`)
+//line messages.qtpl:10
+ qw422016.N().DL(AuthUser.RefreshRate)
+//line messages.qtpl:10
+ qw422016.N().S(`">`)
+//line messages.qtpl:10
+ }
+//line messages.qtpl:10
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:11
+ if AuthUser.CollectMetadata {
+//line messages.qtpl:11
+ qw422016.N().S(`<link rel="stylesheet" type="text/css" href="/public/css/meta.css?v=`)
+//line messages.qtpl:11
+ qw422016.E().S(VERSION)
+//line messages.qtpl:11
+ qw422016.N().S(`" />`)
+//line messages.qtpl:11
+ }
+//line messages.qtpl:11
+ qw422016.N().S(`
+
+ <style>
+ /* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+ */
+ html, body, div, span, applet, object, iframe,
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+ a, abbr, acronym, address, big, cite, code,
+ del, dfn, em, img, ins, kbd, q, s, samp,
+ small, strike, strong, sub, sup, tt, var,
+ b, u, i, center,
+ dl, dt, dd, ol, ul, li,
+ fieldset, form, label, legend,
+ table, caption, tbody, tfoot, thead, tr, th, td,
+ article, aside, canvas, details, embed,
+ figure, figcaption, footer, header, hgroup,
+ menu, nav, output, ruby, section, summary,
+ time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+ }
+ /* HTML5 display-role reset for older browsers */
+ article, aside, details, figcaption, figure,
+ footer, header, hgroup, menu, nav, section {
+ display: block;
+ }
+ body {
+ line-height: 1;
+ }
+ ol, ul {
+ list-style: none;
+ }
+ blockquote, q {
+ quotes: none;
+ }
+ blockquote:before, blockquote:after,
+ q:before, q:after {
+ content: '';
+ content: none;
+ }
+ table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+ /* --- end --- */
+
+
+ i { font-style: italic; }
+
+ /* Remove button padding in FF */
+ button::-moz-focus-inner {
+ border:0;
+ padding:0;
+ }
+
+ body { font-family: Lato,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; }
+ a { color: #00bc8c; text-decoration: none; }
+ a:hover { color: #007053; text-decoration: underline; }
+ .unread_room { color: #2392da; text-decoration: none; }
+ .unread_room:hover { color: #004970; text-decoration: underline; }
+ .emoji {
+ font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;
+ font-size: 17px;
+ }
+ .mod-btn {
+ width: 16px; height: 16px;
+ margin: 0; padding: 0;
+ border: 1px solid gray;
+ display: inline;
+ text-align: center;
+ vertical-align: middle;
+ user-select: none;
+ background-color: #444;
+ color: #ea2a2a;
+ -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.25);
+ -moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.25);
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ }
+ .mod-btn:hover {
+ background-color: #222;
+ }
+ .delete_msg_btn {
+ font-size: 15px;
+ line-height: 1;
+ }
+ .delete_msg_btn::after { content: "×"; }
+ .hb_btn {
+ font-size: 10px;
+ line-height: 1.4;
+ }
+ .hb_btn::after { content: "hb"; }
+ .k_btn {
+ font-size: 10px;
+ line-height: 1.4;
+ }
+ .k_btn::after { content: "k"; }
+ #manualrefresh {
+ `)
+//line messages.qtpl:115
+ if !Data.ForceManualRefresh {
+//line messages.qtpl:115
+ qw422016.N().S(`
+ top: -200%;
+ animation: timeout_messages `)
+//line messages.qtpl:117
+ qw422016.N().DL(Data.ManualRefreshTimeout)
+//line messages.qtpl:117
+ qw422016.N().S(`s forwards;
+ `)
+//line messages.qtpl:118
+ }
+//line messages.qtpl:118
+ qw422016.N().S(`
+ color: #bf2718;
+ display: block;
+ position: fixed;
+ text-align: center;
+ left: calc(50% - 200px);
+ width: 400px;
+ z-index: 2;
+ background-color: #500000;
+ border: 2px solid #ff0000;
+ }
+ @keyframes timeout_messages {
+ 0% { top: -200%; }
+ 99% { top: -200%; }
+ 100% { top: 0; }
+ }
+ .date { color: #999; font-family: 'Courier New', Courier, monospace; font-size: 14px; }
+ .date-link:hover { color: #999; text-decoration: underline; }
+ .sysmsg { color: #fff; font-family: 'Courier New', Courier, monospace; font-size: 14px; }
+ small { font-size: 80%; font-weight: 400; }
+ .msg { padding: 3px 0 3px 8px; border-bottom: 1px solid #444; color: #888; position: relative; }
+ .msg p:first-of-type { display: inline; }
+ strong { font-weight: bold; }
+ em { font-style: italic; }
+ pre { border: 1px solid #2b442b; padding: 2px; margin: 2px 0; max-height: 300px; overflow: auto; background-color: rgba(39,40,34,0.6) !important;
+ font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; }
+ code { border: 1px solid #2b442b; color: #f92672; padding: 0 2px; margin: 0px 0; background-color: rgba(39,40,34,0.6) !important; }
+ .censored { background-color: black; color: black; padding: 0 3px; }
+ .censored:hover { background-color: black; color: white; }
+ ul { list-style-type: disc; margin: 0 0 0 15px; }
+ * {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+ .afk-indicator { color: #ff9a27; }
+ .spacer16 { display: inline-block; width: 16px; }
+ .spacer36 { display: inline-block; width: 36px; }
+ .spacer56 { display: inline-block; width: 56px; }
+ .d-inline { display: inline; }
+ .o-wrap { overflow-wrap: break-word; }
+ .f-def-clr { color: #888; }
+ .f-orange-clr { color: orange; }
+ .f-white-clr, .f-white-clr:hover { color: white; }
+ .line-through { text-decoration: line-through; }
+ .hb-row { background-color: rgba(0, 0, 0, 0.7); opacity: `)
+//line messages.qtpl:162
+ qw422016.N().F(AuthUser.GetHellbanOpacityF64())
+//line messages.qtpl:162
+ qw422016.N().S(`; }
+ .own-highlight { background-color: rgba(255,241,176,0.05); }
+ .read-marker { border-top: `)
+//line messages.qtpl:164
+ qw422016.N().DL(AuthUser.ChatReadMarkerSize)
+//line messages.qtpl:164
+ qw422016.N().S(`px solid `)
+//line messages.qtpl:164
+ qw422016.E().S(AuthUser.ChatReadMarkerColor)
+//line messages.qtpl:164
+ qw422016.N().S(`; }
+ #msgs { `)
+//line messages.qtpl:165
+ if !AuthUser.HideRightColumn {
+//line messages.qtpl:165
+ qw422016.N().S(`width: calc(100% - 170px); float: left; `)
+//line messages.qtpl:165
+ }
+//line messages.qtpl:165
+ qw422016.N().S(`line-height: 1.2; }
+ #no-msg { padding-left: 10px; color: #ddd; }
+ #rgt-pane { width: 150px; height: 100%; float: left; margin-left: 20px; position: fixed; right: 0; overflow-y: auto; line-height: 1.15; }
+ .rgt-title { font-weight: bolder; color: #ced4da; }
+ .mb-20px { margin-bottom: 20px; }
+ .mb-30px { margin-bottom: 30px; }
+ .mt-5px { margin-top: 5px; }
+ .mt-10px { margin-top: 10px; }
+ .notif, .notif:hover { color: #e74c3c; }
+ #msg-err { background-color: #8f2d2d; color: #ffffff; padding: 1px 5px 2px 5px; display: block; text-decoration: none; }
+ </style>
+ </head>
+ <body>
+
+ `)
+//line messages.qtpl:179
+ if Data.ForceManualRefresh {
+//line messages.qtpl:179
+ qw422016.N().S(`
+ <div id="manualrefresh">
+ <h4>Manual refresh required</h4>
+ <form method="get" action="/chat/`)
+//line messages.qtpl:182
+ qw422016.E().S(Data.RoomName)
+//line messages.qtpl:182
+ qw422016.N().S(`" target="_top">
+ <input type="submit" value="Reload" />
+ </form>
+ </div>
+ `)
+//line messages.qtpl:186
+ } else if !Data.PreventRefresh {
+//line messages.qtpl:186
+ qw422016.N().S(`
+ <div id="manualrefresh">
+ <h4>Manual refresh required</h4>
+ <form method="get">
+ <input type="submit" value="Reload" />
+ </form>
+ </div>
+ `)
+//line messages.qtpl:193
+ }
+//line messages.qtpl:193
+ qw422016.N().S(`
+
+ `)
+//line messages.qtpl:195
+ if Data.Error != "" {
+//line messages.qtpl:195
+ qw422016.N().S(`
+ <a href="/api/v1/chat/messages/`)
+//line messages.qtpl:196
+ qw422016.E().S(Data.RoomName)
+//line messages.qtpl:196
+ qw422016.N().S(`" id="msg-err">× `)
+//line messages.qtpl:196
+ qw422016.E().S(Data.Error)
+//line messages.qtpl:196
+ qw422016.N().S(`</a>
+ `)
+//line messages.qtpl:197
+ }
+//line messages.qtpl:197
+ qw422016.N().S(`
+
+ `)
+//line messages.qtpl:199
+ if Data.PmSound || Data.TaggedSound {
+//line messages.qtpl:199
+ qw422016.N().S(`
+ <audio src="/public/mp3/sound5.mp3" autoplay></audio>
+ `)
+//line messages.qtpl:201
+ } else if Data.NewMessageSound {
+//line messages.qtpl:201
+ qw422016.N().S(`
+ <audio src="/public/mp3/sound6.mp3" autoplay></audio>
+ `)
+//line messages.qtpl:203
+ }
+//line messages.qtpl:203
+ qw422016.N().S(`
+
+ <div id="msgs">
+ `)
+//line messages.qtpl:207
+ baseTopBarURL := "/api/v1/chat/top-bar/" + Data.RoomName
+ readMarkerRendered := false
+ isFirstMsg := true
+
+//line messages.qtpl:210
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:211
+ for idx, e := range Data.Messages {
+//line messages.qtpl:211
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:212
+ if e.UserCanSee(*AuthUser) {
+//line messages.qtpl:212
+ qw422016.N().S(`
+ <div id="msgid-`)
+//line messages.qtpl:213
+ qw422016.E().S(e.UUID)
+//line messages.qtpl:213
+ qw422016.N().S(`" class="msg
+ `)
+//line messages.qtpl:214
+ if (e.User.IsHellbanned || e.IsHellbanned) && AuthUser.DisplayHellbanned {
+//line messages.qtpl:214
+ qw422016.N().S(` hb-row
+ `)
+//line messages.qtpl:215
+ } else if AuthUser.ID == e.User.ID && AuthUser.HighlightOwnMessages {
+//line messages.qtpl:215
+ qw422016.N().S(` own-highlight`)
+//line messages.qtpl:215
+ }
+//line messages.qtpl:215
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:216
+ if AuthUser.ChatReadMarkerEnabled && e.CreatedAt.Before(Data.ReadMarker.ReadAt) && !readMarkerRendered {
+//line messages.qtpl:216
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:217
+ if idx > 0 {
+//line messages.qtpl:217
+ qw422016.N().S(` read-marker`)
+//line messages.qtpl:217
+ }
+//line messages.qtpl:217
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:219
+ readMarkerRendered = true
+
+//line messages.qtpl:220
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:221
+ }
+//line messages.qtpl:221
+ qw422016.N().S(`
+ ">
+ `)
+//line messages.qtpl:223
+ if e.UserCanDelete(*AuthUser) {
+//line messages.qtpl:223
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:224
+ if !e.TooOldToDelete() {
+//line messages.qtpl:224
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:225
+ if AuthUser.DisplayDeleteButton {
+//line messages.qtpl:225
+ qw422016.N().S(`
+ <form method="post" action="/api/v1/chat/messages/delete/`)
+//line messages.qtpl:226
+ qw422016.E().S(e.UUID)
+//line messages.qtpl:226
+ qw422016.N().S(`" class="d-inline">
+ <input type="hidden" name="csrf" value="`)
+//line messages.qtpl:227
+ qw422016.E().S(CSRF)
+//line messages.qtpl:227
+ qw422016.N().S(`" />
+ <button class="mod-btn delete_msg_btn" title="delete"></button>
+ </form>
+ `)
+//line messages.qtpl:230
+ }
+//line messages.qtpl:230
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:231
+ } else if (AuthUser.IsModerator() && e.TooOldToDelete() && e.UserID != AuthUser.ID) || AuthUser.IsAdmin || (e.Room.OwnerUserID != nil && *e.Room.OwnerUserID == AuthUser.ID) {
+//line messages.qtpl:231
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:232
+ if AuthUser.DisplayDeleteButton {
+//line messages.qtpl:232
+ qw422016.N().S(`
+ <form method="post" action="/api/v1/chat/messages/delete/`)
+//line messages.qtpl:233
+ qw422016.E().S(e.UUID)
+//line messages.qtpl:233
+ qw422016.N().S(`" class="d-inline">
+ <input type="hidden" name="csrf" value="`)
+//line messages.qtpl:234
+ qw422016.E().S(CSRF)
+//line messages.qtpl:234
+ qw422016.N().S(`" />
+ <button class="mod-btn delete_msg_btn f-orange-clr" title="delete"></button>
+ </form>
+ `)
+//line messages.qtpl:237
+ }
+//line messages.qtpl:237
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:238
+ } else if AuthUser.IsModerator() {
+//line messages.qtpl:238
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:239
+ if AuthUser.DisplayDeleteButton {
+//line messages.qtpl:239
+ qw422016.N().S(`
+ <div class="spacer16"></div>
+ `)
+//line messages.qtpl:241
+ }
+//line messages.qtpl:241
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:242
+ } else {
+//line messages.qtpl:242
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:243
+ if AuthUser.DisplayDeleteButton {
+//line messages.qtpl:243
+ qw422016.N().S(`
+ <div class="spacer16"></div>
+ `)
+//line messages.qtpl:245
+ }
+//line messages.qtpl:245
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:246
+ }
+//line messages.qtpl:246
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:247
+ if AuthUser.IsModerator() {
+//line messages.qtpl:247
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:248
+ if e.UserID != AuthUser.ID {
+//line messages.qtpl:248
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:249
+ if AuthUser.DisplayHellbanButton {
+//line messages.qtpl:249
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:250
+ if e.User.Username == NullUsername {
+//line messages.qtpl:250
+ qw422016.N().S(`
+ <div class="spacer16"></div>
+ `)
+//line messages.qtpl:252
+ } else {
+//line messages.qtpl:252
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:253
+ if e.User.IsHellbanned {
+//line messages.qtpl:253
+ qw422016.N().S(`
+ <form method="post" action="/api/v1/users/`)
+//line messages.qtpl:254
+ qw422016.E().S(e.UserID.String())
+//line messages.qtpl:254
+ qw422016.N().S(`/unhellban" class="d-inline">
+ <input type="hidden" name="csrf" value="`)
+//line messages.qtpl:255
+ qw422016.E().S(CSRF)
+//line messages.qtpl:255
+ qw422016.N().S(`" />
+ <button class="mod-btn hb_btn f-orange-clr line-through" title="unhellban"></button>
+ </form>
+ `)
+//line messages.qtpl:258
+ } else {
+//line messages.qtpl:258
+ qw422016.N().S(`
+ <form method="post" action="/api/v1/users/`)
+//line messages.qtpl:259
+ qw422016.E().S(e.UserID.String())
+//line messages.qtpl:259
+ qw422016.N().S(`/hellban" class="d-inline">
+ <input type="hidden" name="csrf" value="`)
+//line messages.qtpl:260
+ qw422016.E().S(CSRF)
+//line messages.qtpl:260
+ qw422016.N().S(`" />
+ <button class="mod-btn hb_btn f-orange-clr" title="hellban"></button>
+ </form>
+ `)
+//line messages.qtpl:263
+ }
+//line messages.qtpl:263
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:264
+ }
+//line messages.qtpl:264
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:265
+ }
+//line messages.qtpl:265
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:266
+ if AuthUser.DisplayKickButton {
+//line messages.qtpl:266
+ qw422016.N().S(`
+ <form method="post" action="/api/v1/users/`)
+//line messages.qtpl:267
+ qw422016.E().S(e.UserID.String())
+//line messages.qtpl:267
+ qw422016.N().S(`/kick" class="d-inline">
+ <input type="hidden" name="csrf" value="`)
+//line messages.qtpl:268
+ qw422016.E().S(CSRF)
+//line messages.qtpl:268
+ qw422016.N().S(`" />
+ <button class="mod-btn k_btn f-orange-clr" title="kick"></button>
+ </form>
+ `)
+//line messages.qtpl:271
+ }
+//line messages.qtpl:271
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:272
+ } else {
+//line messages.qtpl:272
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:273
+ if AuthUser.DisplayKickButton && AuthUser.DisplayHellbanButton {
+//line messages.qtpl:273
+ qw422016.N().S(`
+ <div class="spacer36"></div>
+ `)
+//line messages.qtpl:275
+ } else if AuthUser.DisplayKickButton || AuthUser.DisplayHellbanButton {
+//line messages.qtpl:275
+ qw422016.N().S(`
+ <div class="spacer16"></div>
+ `)
+//line messages.qtpl:277
+ }
+//line messages.qtpl:277
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:278
+ }
+//line messages.qtpl:278
+ qw422016.N().S(`
+`)
+//line messages.qtpl:279
+ }
+//line messages.qtpl:280
+ } else {
+//line messages.qtpl:281
+ if Data.NbButtons == 3 {
+//line messages.qtpl:281
+ qw422016.N().S(` <div class="spacer56"></div>
+`)
+//line messages.qtpl:283
+ } else if Data.NbButtons == 2 {
+//line messages.qtpl:283
+ qw422016.N().S(` <div class="spacer36"></div>
+`)
+//line messages.qtpl:285
+ } else if Data.NbButtons == 1 {
+//line messages.qtpl:285
+ qw422016.N().S(` <div class="spacer16"></div>
+`)
+//line messages.qtpl:287
+ }
+//line messages.qtpl:288
+ }
+//line messages.qtpl:289
+ if Data.DateFormat != "" {
+//line messages.qtpl:289
+ qw422016.N().S(` <a href="`)
+//line messages.qtpl:290
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:290
+ qw422016.N().S(`?quote=`)
+//line messages.qtpl:290
+ qw422016.E().S(e.UUID)
+//line messages.qtpl:290
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:290
+ qw422016.N().S(`" target="iframe1" class="date date-link" title="`)
+//line messages.qtpl:290
+ qw422016.E().S(e.CreatedAt.Format("01-02 15:04:05"))
+//line messages.qtpl:290
+ if isFirstMsg {
+//line messages.qtpl:290
+ qw422016.N().S(` (`)
+//line messages.qtpl:290
+ qw422016.E().S(humanize.Time(e.CreatedAt))
+//line messages.qtpl:290
+ qw422016.N().S(`)`)
+//line messages.qtpl:290
+ }
+//line messages.qtpl:290
+ qw422016.N().S(`">`)
+//line messages.qtpl:290
+ qw422016.E().S(e.CreatedAt.Format(Data.DateFormat))
+//line messages.qtpl:290
+ qw422016.N().S(`</a>
+ `)
+//line messages.qtpl:291
+ isFirstMsg = false
+
+//line messages.qtpl:291
+ qw422016.N().S(`
+`)
+//line messages.qtpl:292
+ }
+//line messages.qtpl:292
+ qw422016.N().S(` <a href="/u/`)
+//line messages.qtpl:293
+ qw422016.E().S(e.GetProfile(AuthUser))
+//line messages.qtpl:293
+ qw422016.N().S(`" target="_blank" class="f-def-clr">-</a>
+`)
+//line messages.qtpl:294
+ if e.System {
+//line messages.qtpl:294
+ qw422016.N().S(` <span class="sysmsg">`)
+//line messages.qtpl:295
+ streamunesc(qw422016, e.Message)
+//line messages.qtpl:295
+ qw422016.N().S(`</span>
+`)
+//line messages.qtpl:296
+ } else {
+//line messages.qtpl:297
+ if e.Moderators {
+//line messages.qtpl:297
+ qw422016.N().S(`<span class="sysmsg">[<a href="`)
+//line messages.qtpl:297
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:297
+ qw422016.N().S(`?m=1`)
+//line messages.qtpl:297
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:297
+ qw422016.N().S(`" target="iframe1" class="sysmsg f-white-clr">M</a>]</span> `)
+//line messages.qtpl:297
+ }
+//line messages.qtpl:298
+ if e.GroupID != nil {
+//line messages.qtpl:298
+ qw422016.N().S(`<span class="sysmsg">[<a href="`)
+//line messages.qtpl:298
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:298
+ qw422016.N().S(`?g=`)
+//line messages.qtpl:298
+ qw422016.E().S(e.Group.Name)
+//line messages.qtpl:298
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:298
+ qw422016.N().S(`" target="iframe1" class="sysmsg f-white-clr">`)
+//line messages.qtpl:298
+ qw422016.E().S(e.Group.Name)
+//line messages.qtpl:298
+ qw422016.N().S(`</a>]</span> `)
+//line messages.qtpl:298
+ }
+//line messages.qtpl:299
+ if e.ToUserID != nil {
+//line messages.qtpl:299
+ qw422016.N().S(` [`)
+//line messages.qtpl:300
+ streamfromUsername(qw422016, AuthUser, Data, e, baseTopBarURL)
+//line messages.qtpl:300
+ qw422016.N().S(` →
+`)
+//line messages.qtpl:302
+ if e.ToUser.ID == AuthUser.ID {
+//line messages.qtpl:302
+ qw422016.N().S(`<span `)
+//line messages.qtpl:302
+ streamunesc(qw422016, e.ToUser.GenerateChatStyle())
+//line messages.qtpl:302
+ qw422016.N().S(`>`)
+//line messages.qtpl:302
+ qw422016.E().S(e.ToUser.Username)
+//line messages.qtpl:302
+ qw422016.N().S(`</span>`)
+//line messages.qtpl:302
+ } else {
+//line messages.qtpl:302
+ qw422016.N().S(`<a `)
+//line messages.qtpl:302
+ streamunesc(qw422016, e.ToUser.GenerateChatStyle())
+//line messages.qtpl:302
+ qw422016.N().S(` href="`)
+//line messages.qtpl:302
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:302
+ qw422016.N().S(`?pm=`)
+//line messages.qtpl:302
+ qw422016.E().S(e.ToUser.Username)
+//line messages.qtpl:302
+ qw422016.E().S(Data.TopBarQueryParams)
+//line messages.qtpl:302
+ qw422016.N().S(`" target="iframe1">`)
+//line messages.qtpl:302
+ qw422016.E().S(e.ToUser.Username)
+//line messages.qtpl:302
+ qw422016.N().S(`</a>`)
+//line messages.qtpl:302
+ }
+//line messages.qtpl:302
+ qw422016.N().S(`] -
+`)
+//line messages.qtpl:303
+ } else {
+//line messages.qtpl:304
+ streamfromUsername(qw422016, AuthUser, Data, e, baseTopBarURL)
+//line messages.qtpl:305
+ if !e.IsMe() {
+//line messages.qtpl:306
+ if AuthUser.CanSeeHB() && (e.IsHellbanned || e.User.IsHellbanned) && (e.ToUserID == nil) {
+//line messages.qtpl:306
+ qw422016.N().S(` <a href="`)
+//line messages.qtpl:307
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:307
+ qw422016.N().S(`?hbm=1`)
+//line messages.qtpl:307
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:307
+ qw422016.N().S(`" target="iframe1" class="f-def-clr">-</a>
+`)
+//line messages.qtpl:308
+ } else {
+//line messages.qtpl:308
+ qw422016.N().S(` -
+`)
+//line messages.qtpl:310
+ }
+//line messages.qtpl:311
+ }
+//line messages.qtpl:312
+ }
+//line messages.qtpl:312
+ qw422016.N().S(` <span `)
+//line messages.qtpl:313
+ streamunesc(qw422016, e.User.GenerateChatStyle())
+//line messages.qtpl:313
+ qw422016.N().S(`><span class="o-wrap">`)
+//line messages.qtpl:313
+ qw422016.N().S(unesc(e.MsgToDisplay()))
+//line messages.qtpl:313
+ qw422016.N().S(`</span></span>
+`)
+//line messages.qtpl:314
+ }
+//line messages.qtpl:314
+ qw422016.N().S(` </div>
+`)
+//line messages.qtpl:316
+ }
+//line messages.qtpl:316
+ qw422016.N().S(` `)
+//line messages.qtpl:317
+ }
+//line messages.qtpl:317
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:318
+ if len(Data.Messages) == 0 {
+//line messages.qtpl:318
+ qw422016.N().S(`
+ <div id="no-msg"><em>No message yet</em></div>
+ `)
+//line messages.qtpl:320
+ }
+//line messages.qtpl:320
+ qw422016.N().S(`
+ </div>
+
+ `)
+//line messages.qtpl:323
+ if !AuthUser.HideRightColumn {
+//line messages.qtpl:323
+ qw422016.N().S(`
+ <div id="rgt-pane">
+ <div class="mb-20px">
+ <div class="rgt-title">Inbox (<a href="/settings/inbox" target="_top"`)
+//line messages.qtpl:326
+ if Data.InboxCount > 0 {
+//line messages.qtpl:326
+ qw422016.N().S(`class="notif"`)
+//line messages.qtpl:326
+ }
+//line messages.qtpl:326
+ qw422016.N().S(`>`)
+//line messages.qtpl:326
+ qw422016.N().DL(Data.InboxCount)
+//line messages.qtpl:326
+ qw422016.N().S(`</a>)</div>
+ </div>
+ <div class="mb-20px">
+ <div class="rgt-title">Rooms:</div>
+ `)
+//line messages.qtpl:330
+ for _, e := range Data.OfficialRooms {
+//line messages.qtpl:330
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:331
+ if e.Name == "club" {
+//line messages.qtpl:331
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:332
+ if AuthUser.IsClubMember {
+//line messages.qtpl:332
+ qw422016.N().S(`
+ <div><a href="/chat/club" target="_top"`)
+//line messages.qtpl:333
+ if e.IsUnread {
+//line messages.qtpl:333
+ qw422016.N().S(` class="unread_room"`)
+//line messages.qtpl:333
+ }
+//line messages.qtpl:333
+ qw422016.N().S(`>#club</a></div>
+ `)
+//line messages.qtpl:334
+ }
+//line messages.qtpl:334
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:335
+ } else if e.Name == "moderators" {
+//line messages.qtpl:335
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:336
+ if AuthUser.IsModerator() {
+//line messages.qtpl:336
+ qw422016.N().S(`
+ <div><a href="/chat/moderators" target="_top"`)
+//line messages.qtpl:337
+ if e.IsUnread {
+//line messages.qtpl:337
+ qw422016.N().S(` class="unread_room"`)
+//line messages.qtpl:337
+ }
+//line messages.qtpl:337
+ qw422016.N().S(`>#moderators</a></div>
+ `)
+//line messages.qtpl:338
+ }
+//line messages.qtpl:338
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:339
+ } else {
+//line messages.qtpl:339
+ qw422016.N().S(`
+ <div><a href="/chat/`)
+//line messages.qtpl:340
+ qw422016.E().S(e.Name)
+//line messages.qtpl:340
+ qw422016.N().S(`" target="_top"`)
+//line messages.qtpl:340
+ if e.IsUnread {
+//line messages.qtpl:340
+ qw422016.N().S(` class="unread_room"`)
+//line messages.qtpl:340
+ }
+//line messages.qtpl:340
+ qw422016.N().S(`>#`)
+//line messages.qtpl:340
+ qw422016.E().S(e.Name)
+//line messages.qtpl:340
+ qw422016.N().S(`</a></div>
+ `)
+//line messages.qtpl:341
+ }
+//line messages.qtpl:341
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:342
+ }
+//line messages.qtpl:342
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:343
+ if len(Data.SubscribedRooms) > 0 {
+//line messages.qtpl:343
+ qw422016.N().S(`
+ <div class="mt-10px"></div>
+ `)
+//line messages.qtpl:345
+ for _, e := range Data.SubscribedRooms {
+//line messages.qtpl:345
+ qw422016.N().S(`
+ <div><a href="/chat/`)
+//line messages.qtpl:346
+ qw422016.E().S(e.Name)
+//line messages.qtpl:346
+ qw422016.N().S(`" target="_top"`)
+//line messages.qtpl:346
+ if e.IsUnread {
+//line messages.qtpl:346
+ qw422016.N().S(` class="unread_room"`)
+//line messages.qtpl:346
+ }
+//line messages.qtpl:346
+ qw422016.N().S(`>#`)
+//line messages.qtpl:346
+ qw422016.E().S(e.Name)
+//line messages.qtpl:346
+ qw422016.N().S(`</a></div>
+ `)
+//line messages.qtpl:347
+ }
+//line messages.qtpl:347
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:348
+ }
+//line messages.qtpl:348
+ qw422016.N().S(`
+ <div class="mt-5px"><a href="/rooms" target="_top">[...]</a></div>
+ </div>
+ <div class="mb-20px">
+ <div class="rgt-title">In this room:</div>
+ `)
+//line messages.qtpl:353
+ for _, e := range Data.Members {
+//line messages.qtpl:353
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:354
+ StreamMember(qw422016, AuthUser, Data, e)
+//line messages.qtpl:354
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:355
+ }
+//line messages.qtpl:355
+ qw422016.N().S(`
+ </div>
+ `)
+//line messages.qtpl:357
+ if Data.VisibleMemberInChat || AuthUser.DisplayHellbanned {
+//line messages.qtpl:357
+ qw422016.N().S(`
+ <div class="mb-30px">
+ `)
+//line messages.qtpl:359
+ if len(Data.MembersInChat) > 0 {
+//line messages.qtpl:359
+ qw422016.N().S(`
+ <div class="rgt-title">In other rooms:</div>
+ `)
+//line messages.qtpl:361
+ for _, e := range Data.MembersInChat {
+//line messages.qtpl:361
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:362
+ StreamMember(qw422016, AuthUser, Data, e)
+//line messages.qtpl:362
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:363
+ }
+//line messages.qtpl:363
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:364
+ }
+//line messages.qtpl:364
+ qw422016.N().S(`
+ </div>
+ `)
+//line messages.qtpl:366
+ }
+//line messages.qtpl:366
+ qw422016.N().S(`
+ </div>
+ `)
+//line messages.qtpl:368
+ }
+//line messages.qtpl:368
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:369
+ if AuthUser.CollectMetadata {
+//line messages.qtpl:369
+ qw422016.N().S(`
+ <div class="div_1"></div>
+ <div class="div_2"></div>
+ <div class="div_f0">a</div>
+ `)
+//line messages.qtpl:373
+ }
+//line messages.qtpl:373
+ qw422016.N().S(`
+ </body>
+</html>
+`)
+//line messages.qtpl:376
+}
+
+//line messages.qtpl:376
+func WriteMessages(qq422016 qtio422016.Writer, VERSION, CSRF, NullUsername string, AuthUser *database.User, Data chatMessagesData) {
+//line messages.qtpl:376
+ qw422016 := qt422016.AcquireWriter(qq422016)
+//line messages.qtpl:376
+ StreamMessages(qw422016, VERSION, CSRF, NullUsername, AuthUser, Data)
+//line messages.qtpl:376
+ qt422016.ReleaseWriter(qw422016)
+//line messages.qtpl:376
+}
+
+//line messages.qtpl:376
+func Messages(VERSION, CSRF, NullUsername string, AuthUser *database.User, Data chatMessagesData) string {
+//line messages.qtpl:376
+ qb422016 := qt422016.AcquireByteBuffer()
+//line messages.qtpl:376
+ WriteMessages(qb422016, VERSION, CSRF, NullUsername, AuthUser, Data)
+//line messages.qtpl:376
+ qs422016 := string(qb422016.B)
+//line messages.qtpl:376
+ qt422016.ReleaseByteBuffer(qb422016)
+//line messages.qtpl:376
+ return qs422016
+//line messages.qtpl:376
+}
+
+//line messages.qtpl:380
+func StreamMember(qw422016 *qt422016.Writer, AuthUser *database.User, Data chatMessagesData, El managers.UserInfo) {
+//line messages.qtpl:380
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:381
+ baseTopBarURL := "/api/v1/chat/top-bar/" + Data.RoomName
+
+//line messages.qtpl:381
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:382
+ if El.Username == AuthUser.Username {
+//line messages.qtpl:382
+ qw422016.N().S(`
+ <div>
+ <span style="color: `)
+//line messages.qtpl:384
+ qw422016.E().S(El.Color)
+//line messages.qtpl:384
+ qw422016.N().S(`;">`)
+//line messages.qtpl:384
+ qw422016.E().S(El.Username)
+//line messages.qtpl:384
+ qw422016.N().S(`</span>
+ `)
+//line messages.qtpl:385
+ if El.AfkIndicatorEnabled {
+//line messages.qtpl:385
+ qw422016.N().S(`
+ <small class="afk-indicator">afk</small>
+ `)
+//line messages.qtpl:387
+ }
+//line messages.qtpl:387
+ qw422016.N().S(`
+ </div>
+ `)
+//line messages.qtpl:389
+ } else {
+//line messages.qtpl:389
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:390
+ if !El.IsHellbanned || AuthUser.ID == El.UserID || (El.IsHellbanned && AuthUser.IsHellbanned) || AuthUser.DisplayHellbanned {
+//line messages.qtpl:390
+ qw422016.N().S(`
+ <div>
+ `)
+//line messages.qtpl:392
+ tagType := "tag"
+
+//line messages.qtpl:392
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:393
+ if AuthUser.CanSeeHB() && El.IsHellbanned {
+//line messages.qtpl:393
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:394
+ tagType = "htag"
+
+//line messages.qtpl:394
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:395
+ }
+//line messages.qtpl:395
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:396
+ qw422016.N().S(`<a href="`)
+//line messages.qtpl:397
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:397
+ qw422016.N().S(`?`)
+//line messages.qtpl:397
+ qw422016.E().S(tagType)
+//line messages.qtpl:397
+ qw422016.N().S(`=`)
+//line messages.qtpl:397
+ qw422016.E().S(El.Username)
+//line messages.qtpl:397
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:397
+ qw422016.N().S(`"target="iframe1"`)
+//line messages.qtpl:399
+ if El.IsHellbanned && AuthUser.DisplayHellbanned {
+//line messages.qtpl:399
+ qw422016.N().S(`class="hb-row"`)
+//line messages.qtpl:399
+ }
+//line messages.qtpl:399
+ qw422016.N().S(`style="color:`)
+//line messages.qtpl:400
+ qw422016.E().S(El.Color)
+//line messages.qtpl:400
+ qw422016.N().S(`;">`)
+//line messages.qtpl:400
+ qw422016.E().S(string(El.Username[0]))
+//line messages.qtpl:400
+ qw422016.N().S(`</a><a href="`)
+//line messages.qtpl:401
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:401
+ qw422016.N().S(`?pm=`)
+//line messages.qtpl:401
+ qw422016.E().S(El.Username)
+//line messages.qtpl:401
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:401
+ qw422016.N().S(`"target="iframe1"`)
+//line messages.qtpl:403
+ if El.IsHellbanned && AuthUser.DisplayHellbanned {
+//line messages.qtpl:403
+ qw422016.N().S(`class="hb-row"`)
+//line messages.qtpl:403
+ }
+//line messages.qtpl:403
+ qw422016.N().S(`style="color:`)
+//line messages.qtpl:404
+ qw422016.E().S(El.Color)
+//line messages.qtpl:404
+ qw422016.N().S(`;">`)
+//line messages.qtpl:404
+ qw422016.E().S(string(El.Username[1 : len(El.Username)-1]))
+//line messages.qtpl:404
+ qw422016.N().S(`</a><a href="/u/`)
+//line messages.qtpl:405
+ qw422016.E().S(El.Username)
+//line messages.qtpl:405
+ qw422016.N().S(`"rel="noopener noreferrer" target="_blank"`)
+//line messages.qtpl:407
+ if El.IsHellbanned && AuthUser.DisplayHellbanned {
+//line messages.qtpl:407
+ qw422016.N().S(`class="hb-row"`)
+//line messages.qtpl:407
+ }
+//line messages.qtpl:407
+ qw422016.N().S(`style="color:`)
+//line messages.qtpl:408
+ qw422016.E().S(El.Color)
+//line messages.qtpl:408
+ qw422016.N().S(`;">`)
+//line messages.qtpl:408
+ qw422016.E().S(string(El.Username[len(El.Username)-1]))
+//line messages.qtpl:408
+ qw422016.N().S(`</a>`)
+//line messages.qtpl:409
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:410
+ if El.AfkIndicatorEnabled {
+//line messages.qtpl:410
+ qw422016.N().S(`
+ <small class="afk-indicator">afk</small>
+ `)
+//line messages.qtpl:412
+ }
+//line messages.qtpl:412
+ qw422016.N().S(`
+ </div>
+ `)
+//line messages.qtpl:414
+ }
+//line messages.qtpl:414
+ qw422016.N().S(`
+ `)
+//line messages.qtpl:415
+ }
+//line messages.qtpl:415
+ qw422016.N().S(`
+`)
+//line messages.qtpl:416
+}
+
+//line messages.qtpl:416
+func WriteMember(qq422016 qtio422016.Writer, AuthUser *database.User, Data chatMessagesData, El managers.UserInfo) {
+//line messages.qtpl:416
+ qw422016 := qt422016.AcquireWriter(qq422016)
+//line messages.qtpl:416
+ StreamMember(qw422016, AuthUser, Data, El)
+//line messages.qtpl:416
+ qt422016.ReleaseWriter(qw422016)
+//line messages.qtpl:416
+}
+
+//line messages.qtpl:416
+func Member(AuthUser *database.User, Data chatMessagesData, El managers.UserInfo) string {
+//line messages.qtpl:416
+ qb422016 := qt422016.AcquireByteBuffer()
+//line messages.qtpl:416
+ WriteMember(qb422016, AuthUser, Data, El)
+//line messages.qtpl:416
+ qs422016 := string(qb422016.B)
+//line messages.qtpl:416
+ qt422016.ReleaseByteBuffer(qb422016)
+//line messages.qtpl:416
+ return qs422016
+//line messages.qtpl:416
+}
+
+//line messages.qtpl:419
+func streamfromUsername(qw422016 *qt422016.Writer, AuthUser *database.User, Data chatMessagesData, El database.ChatMessage, baseTopBarURL string) {
+//line messages.qtpl:420
+ tagType := "tag"
+
+//line messages.qtpl:421
+ if El.ToUserID != nil {
+//line messages.qtpl:422
+ tagType = "pm"
+
+//line messages.qtpl:423
+ } else if AuthUser.CanSeeHB() && (El.IsHellbanned || El.User.IsHellbanned) {
+//line messages.qtpl:424
+ tagType = "htag"
+
+//line messages.qtpl:425
+ } else if AuthUser.IsModerator() && El.Moderators {
+//line messages.qtpl:426
+ tagType = "mtag"
+
+//line messages.qtpl:427
+ }
+//line messages.qtpl:428
+ if El.User.ID == AuthUser.ID {
+//line messages.qtpl:429
+ if El.CanBeEdited() {
+//line messages.qtpl:429
+ qw422016.N().S(`<a `)
+//line messages.qtpl:429
+ streamunesc(qw422016, El.User.GenerateChatStyle())
+//line messages.qtpl:429
+ qw422016.N().S(` href="`)
+//line messages.qtpl:429
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:429
+ qw422016.N().S(`?e=`)
+//line messages.qtpl:429
+ qw422016.E().S(El.CreatedAt.Format("15:04:05"))
+//line messages.qtpl:429
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:429
+ qw422016.N().S(`" target="iframe1">`)
+//line messages.qtpl:429
+ qw422016.E().S(El.User.Username)
+//line messages.qtpl:429
+ qw422016.N().S(`</a>`)
+//line messages.qtpl:429
+ } else {
+//line messages.qtpl:429
+ qw422016.N().S(`<span `)
+//line messages.qtpl:429
+ streamunesc(qw422016, El.User.GenerateChatStyle())
+//line messages.qtpl:429
+ qw422016.N().S(`>`)
+//line messages.qtpl:429
+ qw422016.E().S(El.User.Username)
+//line messages.qtpl:429
+ qw422016.N().S(`</span>`)
+//line messages.qtpl:429
+ }
+//line messages.qtpl:430
+ } else {
+//line messages.qtpl:430
+ qw422016.N().S(`<a `)
+//line messages.qtpl:430
+ streamunesc(qw422016, El.User.GenerateChatStyle())
+//line messages.qtpl:430
+ qw422016.N().S(` href="`)
+//line messages.qtpl:430
+ qw422016.E().S(baseTopBarURL)
+//line messages.qtpl:430
+ qw422016.N().S(`?`)
+//line messages.qtpl:430
+ qw422016.E().S(tagType)
+//line messages.qtpl:430
+ qw422016.N().S(`=`)
+//line messages.qtpl:430
+ qw422016.E().S(El.User.Username)
+//line messages.qtpl:430
+ streamunesc(qw422016, Data.TopBarQueryParams)
+//line messages.qtpl:430
+ qw422016.N().S(`" target="iframe1">`)
+//line messages.qtpl:430
+ qw422016.E().S(El.User.Username)
+//line messages.qtpl:430
+ qw422016.N().S(`</a>`)
+//line messages.qtpl:430
+ }
+//line messages.qtpl:431
+}
+
+//line messages.qtpl:431
+func writefromUsername(qq422016 qtio422016.Writer, AuthUser *database.User, Data chatMessagesData, El database.ChatMessage, baseTopBarURL string) {
+//line messages.qtpl:431
+ qw422016 := qt422016.AcquireWriter(qq422016)
+//line messages.qtpl:431
+ streamfromUsername(qw422016, AuthUser, Data, El, baseTopBarURL)
+//line messages.qtpl:431
+ qt422016.ReleaseWriter(qw422016)
+//line messages.qtpl:431
+}
+
+//line messages.qtpl:431
+func fromUsername(AuthUser *database.User, Data chatMessagesData, El database.ChatMessage, baseTopBarURL string) string {
+//line messages.qtpl:431
+ qb422016 := qt422016.AcquireByteBuffer()
+//line messages.qtpl:431
+ writefromUsername(qb422016, AuthUser, Data, El, baseTopBarURL)
+//line messages.qtpl:431
+ qs422016 := string(qb422016.B)
+//line messages.qtpl:431
+ qt422016.ReleaseByteBuffer(qb422016)
+//line messages.qtpl:431
+ return qs422016
+//line messages.qtpl:431
+}