com.mchange.feedletter.CommandConfig.scala Maven / Gradle / Ivy
package com.mchange.feedletter
import com.mchange.feedletter.style.*
import zio.*
import com.mchange.feedletter.db.{DbVersionStatus,PgDatabase}
import com.mchange.feedletter.style.AllUntemplates
import java.nio.file.{Path as JPath}
import javax.sql.DataSource
import java.time.ZoneId
import com.mchange.conveniences.throwable.*
import com.mchange.conveniences.collection.*
import com.mchange.mailutil.*
import untemplate.Untemplate
import MLevel.*
object CommandConfig extends SelfLogging:
case class AddFeed( nf : NascentFeed ) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
fis <- PgDatabase.addFeed( ds, nf )
_ <- printFeedInfoTable(fis)
yield ()
end zcommand
case class AlterFeed( fts : FeedTimings ) extends CommandConfig:
def ifSomethingToDo( ds : DataSource ) =
val timings = fts._2 :: fts._3 :: fts._4 :: fts._5 :: Nil
if timings.actuals.isEmpty then
ZIO.attempt( println( s"Nothing to do, feed ${fts.feedId} is unchanged." ) )
else
PgDatabase.mergeFeedTimings( ds, fts ) *> ZIO.attempt( println( s"Feed ${fts.feedId} has been updated." ) )
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
_ <- ifSomethingToDo(ds)
yield ()
end zcommand
case class Daemon( fork : Boolean ) extends CommandConfig:
def logMore() =
import java.util.logging.{Level,LogManager,Logger}
val FeedletterLevel = Level.FINER // XXX: Someday, bring this up to Level.INFO
val rootLogger = LogManager.getLogManager().getLogger("")
val packageLogger = Logger.getLogger( "com.mchange.feedletter" )
rootLogger.getHandlers().foreach( _.setLevel(Level.FINEST) )
packageLogger.setLevel(FeedletterLevel)
def writePidFile( pidf : os.Path ) =
val contents = s"${ProcessHandle.current().pid()}${LineSep}"
os.write(pidf, contents)
val onShutdown =
new Thread:
override def run() : Unit = os.remove( pidf )
java.lang.Runtime.getRuntime().addShutdownHook(onShutdown)
override def zcommand : ZCommand =
val task =
for
as <- ZIO.service[AppSetup]
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
_ <- if fork then ZIO.attempt( writePidFile(as.pidFile) ) else ZIO.unit
_ <- if as.loggingConfig == LoggingConfig.Default then ZIO.attempt( logMore() ) else ZIO.unit
_ <- com.mchange.feedletter.Daemon.startup( ds, as )
_ <- SEVERE.zlog( "Unexpected successful completion of perpetual daemon!" )
_ <- ZIO.fail( new UnexpectedDaemonTermination( "Perpetual daemon task appears to have succeddfully terminated!" ) )
yield ()
task.zlogErrorDefect(WARNING, what = "Main daemon")
end zcommand
case object DbDump extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
out <- PgDatabase.dump(ds)
yield
INFO.log(s"The database was successfully dumped to '${out}'.")
end zcommand
case object DbInit extends CommandConfig:
override def zcommand : ZCommand =
def doInit( ds : DataSource, status : DbVersionStatus ) : Task[Unit] =
if status == DbVersionStatus.SchemaMetadataNotFound then PgDatabase.migrate(ds)
else
status match
case DbVersionStatus.Current(_) => ZIO.succeed( INFO.log("The database is already initialized and up-to-date." ) )
case DbVersionStatus.OutOfDate( _, _) => ZIO.succeed( INFO.log("The database is already initialized, but out-of-date. Please migrate.") )
case other => throw new FeedletterException(s"""${other}: ${other.errMessage.getOrElse("")}""")
for
ds <- ZIO.service[DataSource]
status <- PgDatabase.dbVersionStatus(ds)
_ <- doInit( ds, status )
yield ()
end zcommand
case class DbMigrate( force : Boolean ) extends CommandConfig:
override def zcommand : ZCommand =
def doMigrate( ds : DataSource ) = if force then PgDatabase.migrate(ds) else PgDatabase.cautiousMigrate(ds)
for
ds <- ZIO.service[DataSource]
_ <- doMigrate( ds )
yield ()
end zcommand
case class DefineEmailSubscribable[T](
feedId : FeedId,
subscribableName : SubscribableName,
from : String,
replyTo : Option[String],
mbComposeUntemplateName : Option[String],
mbConfirmUntemplateName : Option[String],
mbRemovalNotificationUntemplateName : Option[String],
mbStatusChangeUntemplateName : Option[String],
emailCompanionAndArg : (SubscriptionManager.Email.Companion, Option[T]),
extraParams : Map[String,String]
) extends CommandConfig:
override def zcommand : ZCommand =
val confirmUntemplateName = mbConfirmUntemplateName.getOrElse( Default.Email.ConfirmUntemplate )
val statusChangeUntemplateName = mbStatusChangeUntemplateName.getOrElse( Default.Email.StatusChangeUntemplate )
val removalNotificationUntemplateName = mbRemovalNotificationUntemplateName.getOrElse( Default.Email.RemovalNotificationUntemplate )
val subscriptionManager =
import SubscriptionManager.{Email as SMEM}
emailCompanionAndArg match
case (SMEM.Each, None) =>
val composeUntemplateName = mbComposeUntemplateName.getOrElse( Default.Email.ComposeUntemplateSingle )
SMEM.Each (
from = Destination.Email(from),
replyTo = replyTo.map( Destination.Email.apply ),
composeUntemplateName = composeUntemplateName,
confirmUntemplateName = confirmUntemplateName,
statusChangeUntemplateName = statusChangeUntemplateName,
removalNotificationUntemplateName = removalNotificationUntemplateName,
extraParams = extraParams
)
case (SMEM.Weekly, tz : Option[ZoneId @unchecked]) => // we'll check ourselves
tz.foreach( z => assert( z.isInstanceOf[ZoneId], "Only an Option[ZoneId] should be passed as the extra argument for Email.Weekly. Found '$z'." ) )
val composeUntemplateName = mbComposeUntemplateName.getOrElse( Default.Email.ComposeUntemplateMultiple )
SMEM.Weekly (
from = Destination.Email(from),
replyTo = replyTo.map( Destination.Email.apply ),
composeUntemplateName = composeUntemplateName,
confirmUntemplateName = confirmUntemplateName,
statusChangeUntemplateName = statusChangeUntemplateName,
removalNotificationUntemplateName = removalNotificationUntemplateName,
timeZone = tz,
extraParams = extraParams
)
case (SMEM.Daily, tz : Option[ZoneId @unchecked]) => // we'll check ourselves
tz.foreach( z => assert( z.isInstanceOf[ZoneId], "Only an Option[ZoneId] should be passed as the extra argument for Email.Daily. Found '$z'." ) )
val composeUntemplateName = mbComposeUntemplateName.getOrElse( Default.Email.ComposeUntemplateMultiple )
SMEM.Daily (
from = Destination.Email(from),
replyTo = replyTo.map( Destination.Email.apply ),
composeUntemplateName = composeUntemplateName,
confirmUntemplateName = confirmUntemplateName,
statusChangeUntemplateName = statusChangeUntemplateName,
removalNotificationUntemplateName = removalNotificationUntemplateName,
timeZone = tz,
extraParams = extraParams
)
case (SMEM.Fixed, Some(nipl : Int)) =>
val composeUntemplateName = mbComposeUntemplateName.getOrElse( Default.Email.ComposeUntemplateMultiple )
SMEM.Fixed (
from = Destination.Email(from),
replyTo = replyTo.map( Destination.Email.apply ),
composeUntemplateName = composeUntemplateName,
confirmUntemplateName = confirmUntemplateName,
statusChangeUntemplateName = statusChangeUntemplateName,
removalNotificationUntemplateName = removalNotificationUntemplateName,
numItemsPerLetter = nipl,
extraParams = extraParams
)
case tup @ ( SMEM.Each, Some( whatev ) ) =>
throw new AssertionError( s"Additional argument '$whatev' inconsistent with ${tup(0)}, which accepts no additional arguments." )
case tup @ ( SMEM.Fixed | SMEM.Weekly | SMEM.Daily, Some( whatev ) ) =>
throw new AssertionError( s"Additional argument '$whatev' inconsistent with ${tup(0)}, not of expected type." )
case tup @ ( SMEM.Fixed, None ) =>
throw new AssertionError( s"Missing additional argument (numItemsPerLetter : Int) expected for ${tup(0)}" )
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
tup <- PgDatabase.addSubscribable( ds, subscribableName, feedId, subscriptionManager )
_ <- printSubscribable(tup)
_ <- Console.printLine(s"An email subscribable to feed with ID '${feedId}' named '${subscribableName}' has been created.")
yield ()
end zcommand
case class DefineMastodonSubscribable(
feedId : FeedId,
subscribableName : SubscribableName,
extraParams : Map[String,String]
) extends CommandConfig:
override def zcommand : ZCommand =
val subscriptionManager = SubscriptionManager.Mastodon.Announce( extraParams )
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
tup <- PgDatabase.addSubscribable( ds, subscribableName, feedId, subscriptionManager )
_ <- printSubscribable(tup)
_ <- Console.printLine(s"An email subscribable to feed with ID '${feedId}' named '${subscribableName}' has been created.")
yield ()
end zcommand
case class DropFeedAndSubscribables( feedId : FeedId, removeSubscriptions : Boolean ) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
_ <- PgDatabase.removeFeedAndSubscribables(ds, feedId, removeSubscriptions)
_ <- Console.printLine(s"Feed with ID '${feedId.toInt}' and any subscribables perhaps defined upon it have been permanently removed.")
yield ()
case class DropSubscribable( name : SubscribableName, removeSubscriptions : Boolean ) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
_ <- if removeSubscriptions then PgDatabase.removeSubscribable( ds, name, true ) else PgDatabase.cautiousRemoveSubscribable(ds, name)
_ <- Console.printLine(s"Subscribable '$name' has been permanently removed.")
yield ()
case class EditSubscribable( name : SubscribableName ) extends CommandConfig:
def prettifyJson( jsonStr : String ) : String =
import upickle.default.*
write( read[ujson.Value]( jsonStr ), indent = 4 )
override def zcommand : ZCommand =
def withTemp[T]( op : os.Path => Task[T] ) : Task[T] =
ZIO.acquireReleaseWith( ZIO.attemptBlocking( os.temp() ) )( p => ZIO.succeedBlocking( try os.remove(p) catch NonFatals.PrintStackTrace ))(op)
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
smanJson <- PgDatabase.uninterpretedManagerJsonForSubscribableName( ds, name )
updated <- withTemp { temp =>
for
_ <- ZIO.attemptBlocking( os.write.over(temp, prettifyJson(smanJson)) )
editor = sys.env.get("EDITOR").getOrElse:
throw new EditorNotDefined("Please define environment variable EDITOR if you wish to edit a subscription.")
ec <- ZIO.attemptBlocking( os.proc(List(editor,temp.toString)).call(stdin=os.Inherit,stdout=os.Inherit,stderr=os.Inherit).exitCode )
contents <- ZIO.attemptBlocking( SubscriptionManager.Json( os.read( temp ) ) )
updated <- ZIO.attempt( SubscriptionManager.materialize( contents ) )
yield updated
}
_ <- PgDatabase.updateSubscriptionManagerJson( ds, name, updated )
_ <- Console.printLine(s"Subscription definition '$name' successfully updated.")
yield ()
end zcommand
case class ExportSubscribers(subscribableName : SubscribableName) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
sman <- PgDatabase.subscriptionManagerForSubscribableName( ds, subscribableName )
tups <- PgDatabase.subscriptionsForSubscribableName(ds, subscribableName)
_ <- printSubscriptionsCsv( sman, tups.map( _(1) ) )
yield ()
end zcommand
case object ListConfig extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
tups <- PgDatabase.reportAllConfigKeysStringified( ds )
_ <- printConfigurationTuplesTable(tups)
yield ()
end zcommand
case class ListUntemplates( group : Map[String,Untemplate.AnyUntemplate] ) extends CommandConfig:
override def zcommand : ZCommand =
for
_ <- printUntemplatesTable( group )
yield ()
end zcommand
case object ListExcludedItems extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
eis <- PgDatabase.fetchExcluded(ds)
_ <- printExcludedItemsTable(eis)
yield ()
end zcommand
case object ListFeeds extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
fis <- PgDatabase.listFeeds( ds )
_ <- printFeedInfoTable(fis)
yield ()
end zcommand
case class ListSubscribers(subscribableName : SubscribableName, fullDesc : Option[Boolean]) extends CommandConfig:
def s( d : Destination ) = fullDesc.fold(d.defaultDesc)( fd => if fd then d.fullDesc else d.shortDesc )
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
tups <- PgDatabase.subscriptionsForSubscribableName(ds, subscribableName)
_ <- printSubscriptions( tups.map( ( sid, d, c, a ) => ( sid, s(d), c, a ) ) )
yield ()
end zcommand
case object ListSubscribables extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
tups <- PgDatabase.listSubscribables(ds)
_ <- printSubscribables(tups)
yield ()
end zcommand
case class SendTestEmail( from : String, to : String ) extends CommandConfig:
override def zcommand : ZCommand =
for
as <- ZIO.service[AppSetup]
_ <- ZIO.attemptBlocking:
given Smtp.Context = as.smtpContext
Smtp.sendSimplePlaintext("This is a test message from feedletter.", subject="FEEDLETTER TEST MESSAGE", from=from, to=to )
_ <- Console.printLine( s"Test email sent from '$from' to '$to'." )
yield ()
end zcommand
case class SetConfig( settings : Map[ConfigKey,String] ) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
ss <- PgDatabase.upsertConfigKeyMapAndReport( ds, settings )
_ <- printConfigurationTuplesTable(ss)
yield ()
end zcommand
case class SetExtraParams( subscribableName : SubscribableName, extraParams : Map[String,String], removals : List[String] ) extends CommandConfig:
def updateSubscriptionManager( sman : SubscriptionManager ) : SubscriptionManager =
val currentParams = sman.extraParams
val newParams = (currentParams -- removals) ++ extraParams
sman.withExtraParams(newParams)
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
sman <- PgDatabase.subscriptionManagerForSubscribableName(ds, subscribableName)
updated <- ZIO.attempt( updateSubscriptionManager( sman ) )
_ <- PgDatabase.updateSubscriptionManagerJson( ds, subscribableName, updated )
_ <- ZIO.attempt( println("Updated Subscription Manager: " + updated.jsonPretty) )
yield ()
end zcommand
case class SetUntemplates(
subscribableName : SubscribableName,
composeUntemplateName : Option[String],
confirmUntemplateName : Option[String],
removalNotificationUntemplateName : Option[String],
statusChangeUntemplateName : Option[String]
) extends CommandConfig:
override def zcommand : ZCommand =
def updateSubscriptionManager( sman : SubscriptionManager ) : SubscriptionManager =
val composed = composeUntemplateName.fold(sman): cun =>
sman match
case uc : SubscriptionManager.UntemplatedCompose =>
// verify the named untemplate exists, throw if not found or inappropriate
if uc.isComposeMultiple then AllUntemplates.findComposeUntemplateMultiple(cun) else AllUntemplates.findComposeUntemplateSingle(cun)
uc.withComposeUntemplateName( cun )
case _ =>
val msg = s"Subscribable '${subscribableName}' does not make use of a compose untemplate, can't set its compose untemplate name to '${cun}'."
throw new UnsupportedUntemplateRole(msg)
val confirmed = confirmUntemplateName.fold(composed): cun =>
composed match
case uc : SubscriptionManager.UntemplatedConfirm =>
// verify the named untemplate exists, throw if not found or inappropriate
AllUntemplates.findConfirmUntemplate( cun )
uc.withConfirmUntemplateName( cun )
case _ =>
val msg = s"Subscribable '${subscribableName}' does not make use of a confirm untemplate, can't set its confirm untemplate name to '${cun}'."
throw new UnsupportedUntemplateRole(msg)
val rned = removalNotificationUntemplateName.fold(confirmed): rnun =>
confirmed match
case urn : SubscriptionManager.UntemplatedRemovalNotification =>
// verify the named untemplate exists, throw if not found or inappropriate
AllUntemplates.findRemovalNotificationUntemplate( rnun )
urn.withRemovalNotificationUntemplateName( rnun )
case _ =>
val msg = s"Subscribable '${subscribableName}' does not make use of a removal-notification untemplate, can't set its removal-notification untemplate name to '${rnun}'."
throw new UnsupportedUntemplateRole(msg)
val sced = statusChangeUntemplateName.fold(rned): scun =>
rned match
case usc : SubscriptionManager.UntemplatedStatusChange =>
// verify the named untemplate exists, throw if not found or inappropriate
AllUntemplates.findStatusChangeUntemplate( scun )
usc.withStatusChangeUntemplateName( scun )
case _ =>
val msg = s"Subscribable '${subscribableName}' does not make use of a status-change untemplate, can't set its status-change untemplate name to '${scun}'."
throw new UnsupportedUntemplateRole(msg)
sced
end updateSubscriptionManager
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
sman <- PgDatabase.subscriptionManagerForSubscribableName(ds, subscribableName)
updated <- ZIO.attempt( updateSubscriptionManager( sman ) )
_ <- PgDatabase.updateSubscriptionManagerJson( ds, subscribableName, updated )
_ <- ZIO.attempt( println("Updated Subscription Manager: " + updated.jsonPretty) )
yield ()
end zcommand
case class Subscribe( aso : AdminSubscribeOptions ) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
_ <- PgDatabase.addSubscription( ds, false, aso.subscribableName, aso.destination, aso.confirmed, aso.now )
yield ()
end zcommand
object Style:
def untemplateNameCompose( overrideUntemplateName : Option[String], sman : SubscriptionManager, subscribableName : SubscribableName ) : String =
overrideUntemplateName.getOrElse:
sman match
case stu : SubscriptionManager.UntemplatedCompose => stu.composeUntemplateName
case _ => // XXX: this gives an unreachable code warning, because for now all subscription types are Untemplated. But the may not always be!
throw new InvalidSubscriptionManager(s"Subscription '${subscribableName}' does not compose through an untemplate, cannot style: $sman")
def untemplateNameConfirm( overrideUntemplateName : Option[String], sman : SubscriptionManager, subscribableName : SubscribableName ) : String =
overrideUntemplateName.getOrElse:
sman match
case stu : SubscriptionManager.UntemplatedConfirm => stu.confirmUntemplateName
case _ => // XXX: this gives an unreachable code warning, because for now all subscription types are Untemplated. But the may not always be!
throw new InvalidSubscriptionManager(s"Subscription '${subscribableName}' does not render confirmations through an untemplate, cannot style: $sman")
def untemplateNameStatusChange( overrideUntemplateName : Option[String], sman : SubscriptionManager, subscribableName : SubscribableName ) : String =
overrideUntemplateName.getOrElse:
sman match
case stu : SubscriptionManager.UntemplatedStatusChange => stu.statusChangeUntemplateName
case _ => // XXX: this gives an unreachable code warning, because for now all subscription types are Untemplated. But the may not always be!
throw new InvalidSubscriptionManager(s"Subscription '${subscribableName}' does not render status changes through an untemplate, cannot style: $sman")
def untemplateNameRemovalNotification( overrideUntemplateName : Option[String], sman : SubscriptionManager, subscribableName : SubscribableName ) : String =
overrideUntemplateName.getOrElse:
sman match
case stu : SubscriptionManager.UntemplatedRemovalNotification => stu.removalNotificationUntemplateName
case _ => // XXX: this gives an unreachable code warning, because for now all subscription types are Untemplated. But the may not always be!
throw new InvalidSubscriptionManager(s"Subscription '${subscribableName}' does not render removal notifications through an untemplate, cannot style: $sman")
case class ComposeUntemplateSingle(
subscribableName : SubscribableName,
overrideUntemplateName : Option[String],
selection : ComposeSelection.Single,
destination : Option[Destination],
withinTypeId : Option[String],
interface : String,
port : Int
) extends CommandConfig:
def digest( feedUrl : FeedUrl ) : FeedDigest =
val digest = FeedDigest( feedUrl )
if digest.isEmpty then
throw new NoExampleItems(s"We can't compose against feed '$feedUrl', because it has no example items to render.")
digest
def guid( digest : FeedDigest ) : Guid =
selection match
case ComposeSelection.Single.First =>
digest.fileOrderedGuids.head
case ComposeSelection.Single.Random =>
val n = scala.util.Random.nextInt( digest.fileOrderedGuids.size )
digest.fileOrderedGuids(n)
case ComposeSelection.Single.Guid( guid ) =>
guid
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
pair <- PgDatabase.feedUrlSubscriptionManagerForSubscribableName( ds, subscribableName )
fu = pair(0)
sman = pair(1)
dig = digest( fu )
g = guid( dig )
un = untemplateNameCompose(overrideUntemplateName, sman, subscribableName)
tz <- db.withConnectionTransactional(ds)( conn => sman.bestTimeZone( conn ) )
_ <- styleComposeSingleUntemplate(
un,
subscribableName,
sman,
withinTypeId.getOrElse( sman.sampleWithinTypeId ),
destination.map(sman.narrowDestinationOrThrow).getOrElse(sman.sampleDestination),
tz,
fu,
dig,
g,
interface,
port
).fork
_ <- INFO.zlog( s"HTTP Server started on interface '${interface}', port ${port}" )
_ <- ZIO.never
yield ()
end zcommand
end ComposeUntemplateSingle
case class ComposeUntemplateMultiple(
subscribableName : SubscribableName,
overrideUntemplateName : Option[String],
selection : ComposeSelection.Multiple,
destination : Option[Destination],
withinTypeId : Option[String],
interface : String,
port : Int ) extends CommandConfig:
def digest( feedUrl : FeedUrl ) : FeedDigest =
val digest = FeedDigest( feedUrl )
if digest.isEmpty then
throw new NoExampleItems(s"We can't compose against feed '$feedUrl', because it has no example items to render.")
digest
def guids( digest : FeedDigest ) : Seq[Guid] =
selection match
case ComposeSelection.Multiple.First(n) =>
digest.fileOrderedGuids.take(n).toSeq
case ComposeSelection.Multiple.Random(n) =>
val keepers = scala.util.Random.shuffle( digest.fileOrderedGuids ).take(n).toSet
digest.fileOrderedGuids.filter( keepers )
case ComposeSelection.Multiple.Guids( values ) =>
values
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
pair <- PgDatabase.feedUrlSubscriptionManagerForSubscribableName( ds, subscribableName )
fu = pair(0)
sman = pair(1)
dig = digest( fu )
_ <- if dig.fileOrderedGuids.isEmpty then ZIO.fail( new NoExampleItems( s"Feed currently contains no example items to render: ${fu}" ) ) else ZIO.unit
gs = guids( dig )
_ <- if gs.isEmpty then ZIO.fail( new NoExampleItems( s"${selection} yields no example items to render. Feed size: ${dig.fileOrderedGuids.size}" ) ) else ZIO.unit
un = untemplateNameCompose(overrideUntemplateName, sman, subscribableName)
tz <- db.withConnectionTransactional(ds)( conn => sman.bestTimeZone( conn ) )
_ <- styleComposeMultipleUntemplate(
un,
subscribableName,
sman,
withinTypeId.getOrElse( sman.sampleWithinTypeId ),
destination.map(sman.narrowDestinationOrThrow).getOrElse(sman.sampleDestination),
tz,
fu,
dig,
gs,
interface,
port
).fork
_ <- INFO.zlog( s"HTTP Server started on interface '${interface}', port ${port}" )
_ <- ZIO.never
yield ()
end zcommand
end ComposeUntemplateMultiple
case class Confirm( subscribableName : SubscribableName, overrideUntemplateName : Option[String], destination : Option[Destination], interface : String, port : Int ) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
pair <- PgDatabase.feedUrlSubscriptionManagerForSubscribableName( ds, subscribableName )
fu = pair(0)
sman = pair(1)
un = untemplateNameConfirm(overrideUntemplateName, sman, subscribableName)
ch <- PgDatabase.confirmHours( ds )
_ <- styleConfirmUntemplate(
un,
subscribableName,
sman,
destination.map(sman.narrowDestinationOrThrow).getOrElse(sman.sampleDestination),
fu,
ch,
interface,
port
).fork
_ <- INFO.zlog( s"HTTP Server started on interface '${interface}', port ${port}" )
_ <- ZIO.never
yield ()
end zcommand
case class RemovalNotification( subscribableName : SubscribableName, overrideUntemplateName : Option[String], destination : Option[Destination], interface : String, port : Int ) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
pair <- PgDatabase.feedUrlSubscriptionManagerForSubscribableName( ds, subscribableName )
fu = pair(0)
sman = pair(1)
un = untemplateNameRemovalNotification(overrideUntemplateName, sman, subscribableName)
_ <- styleRemovalNotificationUntemplate(
un,
subscribableName,
sman,
destination.map(sman.narrowDestinationOrThrow).getOrElse(sman.sampleDestination),
interface,
port
).fork
_ <- INFO.zlog( s"HTTP Server started on interface '${interface}', port ${port}" )
_ <- ZIO.never
yield ()
end zcommand
case class StatusChange(
statusChange : SubscriptionStatusChange,
subscribableName : SubscribableName,
overrideUntemplateName : Option[String],
destination : Option[Destination],
requiresConfirmation : Boolean,
interface : String,
port : Int
) extends CommandConfig:
override def zcommand : ZCommand =
for
ds <- ZIO.service[DataSource]
_ <- PgDatabase.ensureDb( ds )
pair <- PgDatabase.feedUrlSubscriptionManagerForSubscribableName( ds, subscribableName )
fu = pair(0)
sman = pair(1)
un = untemplateNameStatusChange(overrideUntemplateName, sman, subscribableName)
_ <- styleStatusChangeUntemplate(
un,
statusChange,
subscribableName,
sman,
destination.map(sman.narrowDestinationOrThrow).getOrElse(sman.sampleDestination),
requiresConfirmation,
interface,
port
).fork
_ <- INFO.zlog( s"HTTP Server started on interface '${interface}', port ${port}" )
_ <- ZIO.never
yield ()
end zcommand
sealed trait CommandConfig:
def zcommand : ZCommand
© 2015 - 2025 Weber Informatics LLC | Privacy Policy