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:
parent
041c99c175
commit
91c0c7b9ef
1 changed files with 35 additions and 26 deletions
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue