switch from presence toggle hack to git-annex tag in presence extended content

Push notifications are actually working over XMPP now!
This commit is contained in:
Joey Hess 2012-10-25 13:04:43 -04:00
parent 041c99c175
commit 91c0c7b9ef

View file

@ -24,6 +24,7 @@ import qualified Data.Text as T
import qualified Data.Set as S import qualified Data.Set as S
import Utility.FileMode import Utility.FileMode
import qualified Git.Branch import qualified Git.Branch
import Data.XML.Types
thisThread :: ThreadName thisThread :: ThreadName
thisThread = "PushNotifier" thisThread = "PushNotifier"
@ -38,7 +39,7 @@ pushNotifierThread st dstatus pushnotifier = NamedThread thisThread $ do
Just jid -> void $ client c jid Just jid -> void $ client c jid
where where
nocreds = do nocreds = do
-- TODO alert error "no creds" -- TODO alert
return () -- exit thread return () -- exit thread
client c jid = runClient server jid (xmppUsername c) (xmppPassword c) $ do client c jid = runClient server jid (xmppUsername c) (xmppPassword c) $ do
@ -55,18 +56,19 @@ pushNotifierThread st dstatus pushnotifier = NamedThread thisThread $ do
sendnotifications = forever $ do sendnotifications = forever $ do
us <- liftIO $ waitPush pushnotifier us <- liftIO $ waitPush pushnotifier
{- Toggle presence to send the notification. -} let payload = [extendedAway, encodePushNotification us]
putStanza $ emptyPresence PresenceUnavailable
putStanza $ (emptyPresence PresenceAvailable) putStanza $ (emptyPresence PresenceAvailable)
{ presenceID = Just $ encodePushNotification us } { presencePayloads = payload }
receivenotifications = forever $ do receivenotifications = forever $ do
s <- getStanza s <- getStanza
liftIO $ print s liftIO $ debug thisThread ["received XMPP:", show s]
case s of case s of
ReceivedPresence (Presence { presenceType = PresenceAvailable, presenceID = Just t }) -> ReceivedPresence p@(Presence { presenceType = PresenceAvailable }) ->
maybe noop (liftIO . pull st dstatus) liftIO $ pull st dstatus $
(decodePushNotification t) concat $ catMaybes $
map decodePushNotification $
presencePayloads p
_ -> noop _ -> noop
{- Everything we need to know to connect to an XMPP server. -} {- Everything we need to know to connect to an XMPP server. -}
@ -102,27 +104,34 @@ xmppCredsFile = do
dir <- fromRepo gitAnnexCredsDir dir <- fromRepo gitAnnexCredsDir
return $ dir </> "notify-xmpp" return $ dir </> "notify-xmpp"
{- A push notification is encoded in the id field of an XMPP presence {- Marks the client as extended away. -}
- notification, in the form: "git-annex-push:uuid[:uuid:...] extendedAway :: Element
- extendedAway = Element (Name (T.pack "show") Nothing Nothing) []
- Git repos can be pushed to that do not have a git-annex uuid; an empty [NodeContent $ ContentText $ T.pack "xa"]
- string is used for those.
-}
prefix :: T.Text
prefix = T.pack "git-annex-push:"
delim :: T.Text {- Name of a git-annex tag, in our own XML namespace.
delim = T.pack ":" - (Not using a namespace URL to avoid unnecessary bloat.) -}
gitAnnexTagName :: Name
gitAnnexTagName = Name (T.pack "git-annex") (Just $ T.pack "git-annex") Nothing
encodePushNotification :: [UUID] -> T.Text pushAttr :: Name
encodePushNotification us = T.concat pushAttr = Name (T.pack "push") Nothing Nothing
[ prefix
, T.intercalate delim $ map (T.pack . fromUUID) us
]
decodePushNotification :: T.Text -> Maybe [UUID] {- git-annex tag with one push attribute per UUID pushed to. -}
decodePushNotification t = map (toUUID . T.unpack) . T.splitOn delim encodePushNotification :: [UUID] -> Element
<$> T.stripPrefix prefix t encodePushNotification us = Element gitAnnexTagName
[(pushAttr, map (ContentText . T.pack . fromUUID) us)] []
decodePushNotification :: Element -> Maybe [UUID]
decodePushNotification (Element name attrs _nodes)
| name == gitAnnexTagName && not (null us) = Just us
| otherwise = Nothing
where
us = concatMap (map (toUUID . T.unpack . fromContent) . snd) $
filter ispush attrs
ispush (k, _) = k == pushAttr
fromContent (ContentText t) = t
fromContent (ContentEntity t) = t
{- We only pull from one remote out of the set listed in the push {- We only pull from one remote out of the set listed in the push
- notification, as an optimisation. - notification, as an optimisation.