cheogram-smtp
created pr with
cheogram-smtp/ignore-empty.1
changed pr name to
Do not send empty emails for empty messages
cmds
checkout latest patchset:
ssh pr.pico.sh pull cheogram-smtp:ignore-empty | git am -3checkout specific patchset revision:
ssh pr.pico.sh pull cheogram-smtp:ignore-empty [rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh cheogram-smtp:ignore-emptyadd comment to patch request:
ssh pr.pico.sh comment cheogram-smtp:ignore-empty "lgtm!"
Patchset
cheogram-smtp/ignore-empty.1
Update version bounds for newer ghc
Stephen Paul Weber
→ hlint clean
2026-10-21T14:19:52ZStephen Paul Weber
make test
2026-10-21T14:43:14ZStephen Paul Weber
This never fails
2026-10-21T14:43:29ZStephen Paul Weber
Do not send empty emails for empty messages
2026-10-21T14:43:41ZStephen Paul Weber
2026-10-21T15:05:03Z
hlint clean
Stephen Paul Weber
2026-10-21T14:43:14ZSemantic diff summary
0 added,
0 modified,
0 signature changed,
0 removed
across 0 analyzed files
(5 files skipped: unsupported file type)
+2
-1
IQManager.hs
#
| ... | ... | @@ -38,7 +39,7 @@ iqSenderUnexceptional responseMapVar iqToSend = do | |
| 38 | 39 | atomicUIO $ modifyTVar' responseMapVar $ | |
| 39 | 40 | Map.insert (XMPP.iqID iqToSend) iqResponseVar | |
| 40 | 41 | return ( | |
| 41 | - | (waitDelay timeout *> pure Nothing) | |
| 42 | + | (waitDelay timeout $> Nothing) | |
| 42 | 43 | `orElse` | |
| 43 | 44 | fmap Just (takeTMVar iqResponseVar) | |
| 44 | 45 | ) |
+3
-3
MMS.hs
#
| ... | ... | @@ -75,12 +75,12 @@ emailToMMS :: | |
| 75 | 75 | -> Maybe (MMS, [(CID.CID, ByteString)]) | |
| 76 | 76 | emailToMMS attachmentUrl ownerT email = do | |
| 77 | 77 | _ <- header "content-type" | |
| 78 | - | mid' <- fmap decodeUtf8 $ header "x-internal-message-id" | |
| 78 | + | mid' <- decodeUtf8 <$> header "x-internal-message-id" | |
| 79 | 79 | time' <- parseTimeM True defaultTimeLocale rfc822DateFormat . | |
| 80 | 80 | textToString . decodeUtf8 =<< | |
| 81 | 81 | header "date" | |
| 82 | - | from' <- addressTel =<< | |
| 83 | - | fmap (Address . MIME.Single) (fromMailbox email) | |
| 82 | + | from' <- addressTel . Address . MIME.Single =<< | |
| 83 | + | fromMailbox email | |
| 84 | 84 | owner' <- addressTel $ AddressLax ownerT | |
| 85 | 85 | return (MMS mid' time' to' from' owner' text' media', files) | |
| 86 | 86 | where |
+3
-2
Util.hs
#
| ... | ... | @@ -6,6 +6,7 @@ import Control.Concurrent.STM (STM, atomically) | |
| 6 | 6 | import Control.Applicative (many) | |
| 7 | 7 | import Control.Concurrent | |
| 8 | 8 | (ThreadId, forkFinally, myThreadId, throwTo) | |
| 9 | + | import Data.Functor (($>)) | |
| 9 | 10 | import Data.Void (absurd) | |
| 10 | 11 | import Control.Error (exceptT) | |
| 11 | 12 | import Data.Time.Clock (UTCTime) |
| ... | ... | @@ -46,7 +47,7 @@ escapeJid txt = mconcat result | |
| 46 | 47 | replace '@' "\\40" <|> | |
| 47 | 48 | fmap Text.singleton Atto.anyChar | |
| 48 | 49 | ) <* Atto.endOfInput) txt | |
| 49 | - | replace c str = Atto.char c *> pure (fromString str) | |
| 50 | + | replace c str = Atto.char c $> fromString str | |
| 50 | 51 | ||
| 51 | 52 | -- XEP-0106 says to only escape \ when absolutely necessary | |
| 52 | 53 | slashEscape :: Atto.Parser Text |
| ... | ... | @@ -66,7 +67,7 @@ unescapeJid txt = fromString result | |
| 66 | 67 | (Atto.char '\\' *> Atto.choice unescapes) <|> | |
| 67 | 68 | Atto.anyChar | |
| 68 | 69 | ) <* Atto.endOfInput) txt | |
| 69 | - | unescapes = map (\(str, c) -> Atto.string (fromString str) *> pure c) [ | |
| 70 | + | unescapes = map (\(str, c) -> Atto.string (fromString str) $> c) [ | |
| 70 | 71 | ("20", ' '), ("22", '"'), ("26", '&'), ("27", '\''), | |
| 71 | 72 | ("2f", '/'), ("3a", ':'), ("3c", '<'), ("3e", '>'), | |
| 72 | 73 | ("40", '@'), ("5c", '\\') |
+2
-2
gateway.hs
#
| ... | ... | @@ -60,7 +60,7 @@ iqSetHandler replyMap componentJid trustedJids iq@XMPP.IQ { | |
| 60 | 60 | } | to == componentJid && bareJid from `elem` trustedJids = do | |
| 61 | 61 | uuid <- liftIO UUID.nextRandom | |
| 62 | 62 | let Just sid = | |
| 63 | - | (XMPP.stanzaID =<< fmap RawComponentStanza payload) <|> | |
| 63 | + | (XMPP.stanzaID . RawComponentStanza =<< payload) <|> | |
| 64 | 64 | Just (UUID.toText uuid) | |
| 65 | 65 | atomicUIO $ STMMap.insert iq (Just sid) replyMap | |
| 66 | 66 | mapM_ XMPP.putStanza $ |
| ... | ... | @@ -199,7 +199,7 @@ iqGetHandler iq@XMPP.IQ { | |
| 199 | 199 | \Part of the Soprani.ca project.") | |
| 200 | 200 | ] | |
| 201 | 201 | where | |
| 202 | - | nodeAttribute = fmap (\node -> (s"node", [XML.ContentText node])) $ | |
| 202 | + | nodeAttribute = (\node -> (s"node", [XML.ContentText node])) <$> | |
| 203 | 203 | XML.attributeText (s"node") p | |
| 204 | 204 | iqGetHandler iq = XMPP.putStanza $ iqError notImplemented iq | |
| 205 | 205 |
+1
-2
test/VCardTest.hs
#
| ... | ... | @@ -29,8 +29,7 @@ data VCardResult = VCardResult VCard XMPP.IQ deriving (Show) | |
| 29 | 29 | instance Arbitrary VCardResult where | |
| 30 | 30 | arbitrary = do | |
| 31 | 31 | vcard <- VCard <$> arbitrary <*> arbitrary <*> arbitrary | |
| 32 | - | iq <- XMPP.IQ <$> | |
| 33 | - | pure XMPP.IQResult <*> | |
| 32 | + | iq <- XMPP.IQ XMPP.IQResult <$> | |
| 34 | 33 | arbitrary <*> | |
| 35 | 34 | arbitrary <*> | |
| 36 | 35 | arbitrary <*> |