Skip to content

Commit

Permalink
open line flag reports from mod timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Feb 7, 2025
1 parent 3dbb731 commit 4f57118
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 20 deletions.
32 changes: 17 additions & 15 deletions modules/api/src/main/ModTimeline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ case class ModTimeline(
appeal: Option[Appeal],
notes: List[Note],
reports: List[Report],
playbanRecord: Option[lila.playban.UserRecord],
flaggedPublicLines: List[PublicLine]
playbanRecord: Option[lila.playban.UserRecord]
):
import ModTimeline.*

Expand All @@ -28,18 +27,21 @@ case class ModTimeline(
val playBans: List[Event] = playbanRecord.so(_.bans.toList).map(pb => PlayBans(NonEmptyList.one(pb)))
val accountCreation: List[Event] = List(AccountCreation(user.createdAt))
val concat: List[Event] =
modLog ::: appealMsgs ::: notes ::: reportEvents ::: playBans ::: flaggedPublicLines ::: accountCreation
modLog ::: appealMsgs ::: notes ::: reportEvents ::: playBans ::: accountCreation
// latest first
concat.sorted(using Ordering.by(at).reverse)

object ModTimeline:

case class ReportNewAtom(report: Report, atoms: NonEmptyList[Report.Atom]):
def like(r: Report): Boolean = report.room == r.room
case class ReportLineFlag(report: Report, line: PublicLine):
def like(r: Report): Boolean = report.id == r.id
def merge(o: ReportLineFlag) = PublicLine.merge(line, o.line).map(l => copy(line = l))
case class PlayBans(list: NonEmptyList[TempBan])
case class AccountCreation(at: Instant)

type Event = Modlog | AppealMsg | Note | ReportNewAtom | PlayBans | PublicLine | AccountCreation
type Event = Modlog | AppealMsg | Note | ReportNewAtom | ReportLineFlag | PlayBans | AccountCreation

def aggregateEvents(events: List[Event]): List[Event] =
events.foldLeft(List.empty[Event])(mergeMany)
Expand All @@ -49,8 +51,8 @@ object ModTimeline:
case (head :: rest, n) => mergeOne(head, n).fold(head :: mergeMany(rest, n))(_ :: rest)

private def mergeOne(prev: Event, next: Event): Option[Event] = (prev, next) match
case (p: PublicLine, n: PublicLine) => PublicLine.merge(p, n)
case (p: PlayBans, n: PlayBans) => PlayBans(n.list ::: p.list).some
case (p: ReportLineFlag, n: ReportLineFlag) if n.like(p.report) => p.merge(n)
case (p: PlayBans, n: PlayBans) => PlayBans(n.list ::: p.list).some
case (p: AppealMsg, n: AppealMsg) if p.by.is(n.by) => p.copy(text = s"${n.text}\n\n${p.text}").some
case (p: ReportNewAtom, n: ReportNewAtom) if n.like(p.report) => p.copy(atoms = n.atoms ::: p.atoms).some
case (p: Modlog, n: Modlog) => mergeModlog(p, n)
Expand All @@ -60,15 +62,16 @@ object ModTimeline:
(p.action == n.action && p.mod.is(n.mod)).option:
p.copy(details = some(List(p.details, n.details).flatten.distinct.mkString(" / ")))

private def reportAtoms(report: Report): List[ReportNewAtom | PublicLine] =
private def reportAtoms(report: Report): List[ReportNewAtom | ReportLineFlag] =
report.atoms
.groupBy(_.text)
.values
.toList
.flatMap: atoms =>
atoms.head.parseFlag match
case None => List(ReportNewAtom(report, atoms))
case Some(flag) => flag.quotes.map(PublicLine(_, flag.source, atoms.head.at))
case None => List(ReportNewAtom(report, atoms))
case Some(flag) =>
flag.quotes.map(text => ReportLineFlag(report, PublicLine(text, flag.source, atoms.head.at)))

extension (e: Event)
def key: String = e match
Expand All @@ -77,7 +80,7 @@ object ModTimeline:
case _: Note => "note"
case _: ReportNewAtom => "report-new"
case _: PlayBans => "playban"
case _: PublicLine => "flagged-line"
case _: ReportLineFlag => "flagged-line"
case _: AccountCreation => "account-creation"
def flair: Flair = Flair:
e match
Expand All @@ -95,15 +98,15 @@ object ModTimeline:
case _: Note => "objects.label"
case _: ReportNewAtom => "symbols.exclamation-mark"
case _: PlayBans => "objects.hourglass-not-done"
case _: PublicLine => "symbols.exclamation-mark"
case _: ReportLineFlag => "symbols.exclamation-mark"
case _: AccountCreation => "food-drink.egg" // how is egg in "food" instead of "animal"
def at: Instant = e match
case e: Modlog => e.date
case e: AppealMsg => e.at
case e: Note => e.date
case ReportNewAtom(_, atoms) => atoms.head.at
case e: PlayBans => e.list.head.date
case e: PublicLine => e.date
case e: ReportLineFlag => e.line.date
case AccountCreation(at) => at
def url(u: User): String = e match
case _: AppealMsg => routes.Appeal.show(u.username).url
Expand All @@ -129,7 +132,7 @@ object ModTimeline:
case Comm => !l.details.has(lila.playban.PlaybanFeedback.sittingAutoPreset.name)
case _ => true
case r: ReportNewAtom if r.report.is(_.Comm) => angle != Angle.Play
case _: PublicLine => angle == Angle.Comm
case r: ReportLineFlag => r.report.open || angle == Angle.Comm
case _ => true

final class ModTimelineApi(
Expand All @@ -153,8 +156,7 @@ final class ModTimelineApi(
reportsAll <- loadReports.so(reportApi.allReportsAbout(user, Max(50)))
reports = reportsAll.filter(filterReport)
playban <- withPlayBans.so(Granter(_.SeeReport)).so(playBanApi.fetchRecord(user))
lines <- Granter(_.ChatTimeout).so(shutupApi.getPublicLines(user.id))
yield ModTimeline(user, modLog, appeal, notes, reports, playban, lines)
yield ModTimeline(user, modLog, appeal, notes, reports, playban)

private def filterModLog(l: Modlog): Boolean =
if l.action == Modlog.teamKick && !modsList.contains(l.mod) then false
Expand Down
17 changes: 12 additions & 5 deletions modules/api/src/main/ui/ModTimelineUi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ final class ModTimelineUi(helpers: Helpers)(
case e: Note => renderNote(e)
case e: ReportNewAtom => renderReportNew(e)
case e: PlayBans => renderPlayBans(e)
case e: PublicLine => renderPublicLine(e)
case e: ReportLineFlag => renderReportLineFlag(e)
case AccountCreation(at) => renderAccountCreation(t.user, at)

private def renderMod(userId: ModId)(using Translate) =
Expand All @@ -88,12 +88,19 @@ final class ModTimelineUi(helpers: Helpers)(
private def renderPlayBans(e: PlayBans) =
frag(pluralize("Playban", e.list.size), ": ", e.list.map(_.mins).toList.mkString(", "), " minutes")

private def renderPublicLine(l: PublicLine)(using Translate) = frag(
"Chat flag",
publicLineSource(l.from),
private def renderReportLineFlag(r: ReportLineFlag)(using Translate) = frag(
if r.report.open
then
postForm(action := s"${routes.Report.inquiry(r.report.id.value)}?onlyOpen=1")(
cls := "mod-timeline__report-form mod-timeline__report-form--open"
)(submitButton("Chat flag")(cls := "button button-thin", title := "Open"))
else "Chat flag",
publicLineSource(r.line.from),
div(cls := "mod-timeline__texts")(
fragList(
PublicLine.merge.split(l.text).map(quote => span(cls := "message")(Analyser.highlightBad(quote))),
PublicLine.merge
.split(r.line.text)
.map(quote => span(cls := "message")(Analyser.highlightBad(quote))),
" | "
)
)
Expand Down

0 comments on commit 4f57118

Please sign in to comment.