Skip to content

Commit

Permalink
Forbid invalid inputs (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmvpm committed May 9, 2024
1 parent 97c4498 commit 37d2353
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 22 deletions.
19 changes: 13 additions & 6 deletions bot/src/main/scala/com/github/mmvpm/bot/state/State.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.mmvpm.bot.state

import com.github.mmvpm.bot.model.{Button, Draft, Tag, TgPhoto}
import com.github.mmvpm.bot.util.PriceUtils.priceText
import com.github.mmvpm.model.{Offer, OfferID}

import scala.util.matching.Regex
Expand Down Expand Up @@ -158,11 +159,14 @@ object State {
s"""
|$summary
|
|С помощью кнопок от 1 до $StepSizeCropped можно выбрать одно объявление, чтобы посмотреть его подробнее
|С помощью $buttonRangeText можно выбрать одно объявление, чтобы посмотреть его подробнее
|""".stripMargin
else
"По вашему запросу ничего не нашлось :("

private lazy val buttonRangeText =
if (StepSizeCropped == 1) "кнопки 1" else s"кнопок от 1 до $StepSizeCropped"

val photos: Seq[TgPhoto] =
offers
.slice(from, from + StepSizeCropped)
Expand All @@ -185,7 +189,7 @@ object State {
.slice(from, from + StepSizeCropped)
.zipWithIndex
.map { case (offer, idx) =>
s"${idx + 1}. ${offer.description.name} (${offer.description.price} рублей)"
s"${idx + 1}. ${offer.description.name} (${priceText(offer.description.price)})"
}
.mkString("\n\n")
}
Expand All @@ -208,7 +212,7 @@ object State {
s"""
|${offer.description.name}
|
|Цена: ${offer.description.price} рублей
|Цена: ${priceText(offer.description.price)}
|
|${offer.description.text}
|
Expand Down Expand Up @@ -270,11 +274,14 @@ object State {
|
|$summary
|
|С помощью кнопок от 1 до $StepSizeCropped можно выбрать одно объявление, чтобы посмотреть его подробнее
|С помощью $buttonRangeText можно выбрать одно объявление, чтобы посмотреть его подробнее
|""".stripMargin
else
"У вас пока что нет ни одного объявления"

private lazy val buttonRangeText =
if (StepSizeCropped == 1) "кнопки 1" else s"кнопок от 1 до $StepSizeCropped"

val photos: Seq[TgPhoto] =
offers
.take(StepSizeCropped)
Expand All @@ -291,7 +298,7 @@ object State {
.take(StepSizeCropped)
.zipWithIndex
.map { case (offer, idx) =>
s"${idx + 1}. ${offer.description.name} (${offer.description.price} рублей)"
s"${idx + 1}. ${offer.description.name} (${priceText(offer.description.price)})"
}
.mkString("\n\n")
}
Expand All @@ -312,7 +319,7 @@ object State {
s"""
|${offer.description.name}
|
|Цена: ${offer.description.price} рублей
|Цена: ${priceText(offer.description.price)}
|
|${offer.description.text}
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,35 +83,48 @@ class StateManagerImpl[F[_]: MonadCancelThrow](ofsManager: OfsManager[F]) extend
private def toCreateOfferName(current: State)(implicit message: Message): F[State] =
CreateOfferName(current).pure

private def toCreateOfferPrice(current: State)(implicit message: Message): F[State] =
message.text match {
case Some(name) => CreateOfferPrice(current, Draft(name = Some(name))).pure
case _ => Error(current, "Пожалуйста, введите название объявления").pure
}
private def toCreateOfferPrice(current: State)(implicit message: Message): F[State] = {
val newState = for {
name <- message.text
if name.containsAtLeastOneLetterOrDigit
} yield CreateOfferPrice(current, Draft(name = Some(name)))

newState
.getOrElse(
Error(current, "Пожалуйста, введите название объявления (должно содержать хотя бы одну букву)")
)
.pure
}

private def toCreateOfferDescription(current: State)(implicit message: Message): F[State] = {
val newState = for {
priceRaw <- message.text
price <- priceRaw.toIntOption
if price >= 0
draft <- current match {
case CreateOfferPrice(_, draft) => Some(draft)
case _ => None
}
updatedDraft = draft.copy(price = Some(price))
} yield CreateOfferDescription(current, updatedDraft)

newState.getOrElse(Error(current, "Пожалуйста, введите цену (целое число рублей)")).pure
newState.getOrElse(Error(current, "Пожалуйста, введите цену (целое число рублей от 0 до 2 млрд)")).pure
}

private def toCreateOfferPhoto(current: State)(implicit message: Message): F[State] =
current match {
case CreateOfferDescription(_, draft) => // description has been uploaded
val newState = for {
description <- message.text
if description.containsAtLeastOneLetterOrDigit
updatedDraft = draft.copy(description = Some(description))
} yield CreateOfferPhoto(current, updatedDraft)

newState.getOrElse(Error(current, "Пожалуйста, введите описание к объявлению")).pure
newState
.getOrElse(
Error(current, "Пожалуйста, введите описание к объявлению (должно содержать хотя бы одну букву)")
)
.pure

case CreateOfferPhoto(_, draft) => // another photo has been uploaded
val newState = for {
Expand Down Expand Up @@ -213,41 +226,41 @@ class StateManagerImpl[F[_]: MonadCancelThrow](ofsManager: OfsManager[F]) extend
current match {
case EditOfferName(_, offerId) =>
message.text match {
case Some(newName) =>
case Some(newName) if newName.containsAtLeastOneLetterOrDigit =>
ofsManager
.updateOffer(offerId, OfferPatch(name = Some(newName)))
.handleDefaultErrors(
current,
ifSuccess = _ => UpdatedOffer(current, s"Название было изменено на \"$newName\"").pure
)
case None =>
Error(current, "Пожалуйста, введите новое название объявления").pure
case _ =>
Error(current, "Пожалуйста, введите новое название объявления (должно содержать хотя бы одну букву)").pure
}

case EditOfferPrice(_, offerId) =>
message.text.flatMap(_.toIntOption) match {
message.text.flatMap(_.toIntOption).filter(_ >= 0) match {
case Some(newPrice) =>
ofsManager
.updateOffer(offerId, OfferPatch(price = Some(newPrice)))
.handleDefaultErrors(
current,
ifSuccess = _ => UpdatedOffer(current, s"Цена была изменена на $newPrice").pure
)
case None =>
Error(current, "Пожалуйста, введите новую цену (целое число рублей)").pure
case _ =>
Error(current, "Пожалуйста, введите новую цену (целое число рублей от 0 до 2 млрд)").pure
}

case EditOfferDescription(_, offerId) =>
message.text match {
case Some(newDescription) =>
case Some(newDescription) if newDescription.containsAtLeastOneLetterOrDigit =>
ofsManager
.updateOffer(offerId, OfferPatch(description = Some(newDescription)))
.handleDefaultErrors(
current,
ifSuccess = _ => UpdatedOffer(current, s"Описание было изменено").pure
)
case None =>
Error(current, "Пожалуйста, введите новое описание объявления").pure
case _ =>
Error(current, "Пожалуйста, введите новое описание объявления (должно содержать хотя бы одну букву)").pure
}

case AddOfferPhoto(_, offerId) =>
Expand Down
16 changes: 16 additions & 0 deletions bot/src/main/scala/com/github/mmvpm/bot/util/PriceUtils.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.github.mmvpm.bot.util

object PriceUtils {

def priceText(price: Int): String =
price match {
case 0 => "Бесплатно"
case _ =>
val suffix = price % 10 match {
case 1 => "рубль"
case 2 | 3 | 4 => "рубля"
case _ => "рублей"
}
s"$price $suffix"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ object StringUtils {

def toUUID: UUID =
UUID.fromString(string)

def containsAtLeastOneLetterOrDigit: Boolean =
string.filter(_ != '\u3164').exists(_.isLetterOrDigit)
}
}

0 comments on commit 37d2353

Please sign in to comment.