contextualOffersSvc.py (10971B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\contextualOffers\client\contextualOffersSvc.py 2 import carbonui.const as uiconst 3 from carbon.common.script.sys.service import Service 4 from contextualOffers.client.UI.omegaOffer.omegaOfferWindow import OmegaOfferWindow 5 from contextualOffers.client.contextualOfferInnerService import ContextualOfferInnerService 6 from contextualOffers.client.offerMocks import MockOmegaOfferAvailable, MockDestroyerBundleOfferAvailable, MockDestroyerBundleAndOmegaOfferAvailable 7 from contextualOffers.client.UI.neocom import UnseenOffersExtension, UnseenOffersBtnData 8 from contextualOffers.common.contextualOfferDataHelpers import flatten_omega_prepared_message 9 from carbonui.uicore import uicore 10 from eve.client.script.ui.shared.neocom.neocom.fixedButtonExtension import SeenItemStorage 11 OFFER_RECEIVED = 0 12 OFFER_PURCHASED = 1 13 SOUND_OFFER_RECEIVED = 'contextual_offer_window_open_play' 14 SOUND_OFFER_BUY_CLICKED = 'contextual_offer_complete_open_play' 15 SOUND_OFFER_PURCHASED = 'purchase_success_play' 16 OFFER_IDS_WITHOUT_BADGING = [1007, 17 1008, 18 1009, 19 1010] 20 21 class ContextualOfferService(Service): 22 __guid__ = 'svc.contextualOfferSvc' 23 __service__ = 'svc.contextualOfferSvc' 24 __notifyevents__ = ['OnOfferReceived', 'OnContextualOfferPurchased', 'OnCharacterSessionChanged'] 25 26 def Run(self, *args, **kwargs): 27 super(ContextualOfferService, self).Run(*args, **kwargs) 28 self.innerService = ContextualOfferInnerService(scatterService=sm) 29 self.wnd = None 30 self.audioService = sm.GetService('audio') 31 self.InitializeNeocomButton() 32 33 def InitializeNeocomButton(self): 34 self._seenOffersStorage = SeenItemStorage(get_items_function=self.GetOfferNotifications, settings_container=settings.user.ui, settings_key='ContextualOffers_SeenOffers') 35 self._neocomOffersNotificationExtension = UnseenOffersExtension(button_data_class=UnseenOffersBtnData, get_badge_count=self.GetNumberOfUnseenOffers, get_item_count=self.GetNumberOfOffers) 36 self._neocomOffersNotificationExtension.connect_item_changes(self._seenOffersStorage.on_items_changed) 37 sm.GetService('neocom').RegisterFixedButtonExtension(self._neocomOffersNotificationExtension) 38 39 def ClearNeocomButton(self): 40 self._neocomOffersNotificationExtension.disconnect_item_changes(self._seenOffersStorage.on_items_changed) 41 try: 42 sm.GetService('neocom').UnregisterFixedButtonExtension(self._neocomOffersNotificationExtension) 43 except ValueError: 44 pass 45 46 def OnCharacterSessionChanged(self, _oldCharacterID, newCharacterID): 47 self.ClearNeocomButton() 48 if newCharacterID: 49 self.InitializeNeocomButton() 50 51 def OnOfferReceived(self, offerID, offer): 52 self.innerService.OnOfferReceived(offerID, offer) 53 self.TrackOfferDelivered(offerID=offerID) 54 self.AddOfferNotification(offerID, OFFER_RECEIVED) 55 56 def OnContextualOfferPurchased(self, offerID, purchaseInfo): 57 self.innerService.OnPurchaseSuccessReceived(offerID=offerID, purchaseObj=purchaseInfo) 58 self.TrackOfferPurchased(offerID=offerID) 59 self.RemoveOfferNotification(offerID, OFFER_RECEIVED) 60 self._OpenPurchaseConfirmedWindow(purchaseInfo) 61 62 def ShouldShowBadgingForOffer(self, offerID): 63 return offerID not in OFFER_IDS_WITHOUT_BADGING 64 65 def GetNumberOfOffers(self): 66 return len(self.GetOfferNotifications() or []) 67 68 def GetNumberOfUnseenOffers(self): 69 unseenOffers = self._seenOffersStorage.get_unseen() 70 availableUnseenOffers = [ offerID for offerID, _ in unseenOffers if self.innerService.IsOfferAvailable(offerID) ] 71 return len(availableUnseenOffers) 72 73 def GetOfferNotifications(self): 74 return set(self.innerService.GetOfferNotifications()) 75 76 def AddOfferNotification(self, offerID, viewType): 77 self.innerService.AddOfferNotification(offerID, viewType) 78 self.CleanupUnavailableOffers() 79 if (offerID, viewType) not in self._seenOffersStorage.seen_items: 80 if self.ShouldShowBadgingForOffer(offerID): 81 self._seenOffersStorage.mark_as_unseen((offerID, viewType)) 82 else: 83 self._seenOffersStorage.mark_as_seen((offerID, viewType)) 84 self._neocomOffersNotificationExtension.notify_of_offers_changed() 85 86 def MarkSeenOfferNotification(self, offerID, viewType): 87 self._seenOffersStorage.mark_as_seen((offerID, viewType)) 88 self._neocomOffersNotificationExtension.notify_of_offers_changed() 89 90 def RemoveOfferNotification(self, offerID, viewType): 91 self.innerService.RemoveOfferNotification(offerID, viewType) 92 self._seenOffersStorage.mark_as_seen((offerID, viewType)) 93 self._neocomOffersNotificationExtension.notify_of_offers_changed() 94 95 def CleanupUnavailableOffers(self): 96 seenOffers = self._seenOffersStorage.seen_items 97 unavailableSeenOffers = set([ (offerID, offerType) for offerID, offerType in seenOffers if not self.innerService.IsOfferAvailable(offerID) ]) 98 self._seenOffersStorage.mark_many_as_unseen(unavailableSeenOffers) 99 100 def GetOffers(self): 101 return self.innerService.GetOffers() 102 103 def GetOffer(self, offerID): 104 return self.innerService.GetOfferById(offerID) 105 106 def IsOfferAvailable(self, offerID): 107 return self.innerService.IsOfferAvailable(offerID) 108 109 def GetPurchasedOffers(self): 110 return self.innerService.GetPurchasedOffers() 111 112 def GetPurchasedOffer(self, offerID): 113 return self.innerService.GetPurchasedOfferById(offerID) 114 115 def IsPurchaseConfirmed(self, offerID): 116 return self.innerService.IsPurchaseConfirmed(offerID) 117 118 def GetLastOfferToken(self): 119 unseenOffers = self._seenOffersStorage.get_unseen() 120 for offerToken in reversed(self.innerService.GetOfferNotifications()): 121 if not unseenOffers or offerToken in unseenOffers: 122 return offerToken 123 124 def OpenContextualOffersWindow(self): 125 offerToken = self.GetLastOfferToken() 126 if offerToken: 127 offerID, viewType = offerToken 128 if self.IsOfferAvailable(offerID): 129 offerInfo = self.GetOffer(offerID) 130 self._OpenPurchaseWindow(offerInfo) 131 return 132 self.LogWarn('Trying to open Contextual Offers window when there are no offers available') 133 134 def DisplayOfferWindowIfActive(self, offerID): 135 if self.IsPurchaseConfirmed(offerID): 136 purchaseInfo = self.GetPurchasedOffer(offerID) 137 self._OpenPurchaseConfirmedWindow(purchaseInfo) 138 elif self.IsOfferAvailable(offerID): 139 offerInfo = self.GetOffer(offerID) 140 self._OpenPurchaseWindow(offerInfo) 141 else: 142 self.LogError('Trying to open Contextual Offer window when there are no offers') 143 144 def _OpenPurchaseWindow(self, offerInfo): 145 offerID = offerInfo['offerID'] 146 offerInfo = flatten_omega_prepared_message(offerInfo) 147 self.TrackOfferIDSeen(offerID) 148 self._OpenWindow(OFFER_RECEIVED, offerInfo) 149 150 def _OpenPurchaseConfirmedWindow(self, purchaseInfo): 151 offerID = purchaseInfo['offerID'] 152 self.TrackOfferPurchasedSeen(offerID) 153 if self.wnd and not self.wnd.destroyed and self.wnd.state != uiconst.UI_HIDDEN: 154 self.wnd.CloseButtonClicked() 155 156 def _OpenWindow(self, viewType, viewInfo): 157 offerID = viewInfo['offerID'] 158 isNewWindow = not self.wnd or self.wnd.destroyed 159 if isNewWindow: 160 self.wnd = OmegaOfferWindow.Open(onOpenCallback=lambda : self._OnWindowOpened(offerID, viewType), onCloseCallback=lambda : self._OnWindowClosed(offerID, viewType)) 161 self.wnd.sr.underlay.SetState(uiconst.UI_HIDDEN) 162 self.innerService.SubscribeToOfferTimer(offerID, self.wnd, self.wnd.OnTimerUpdated) 163 if viewType == OFFER_RECEIVED: 164 self.audioService.SendUIEvent(SOUND_OFFER_RECEIVED) 165 self.wnd.OpenPurchaseView(viewInfo) 166 elif viewType == OFFER_PURCHASED: 167 self.audioService.SendUIEvent(SOUND_OFFER_PURCHASED) 168 self.wnd.OpenConfirmationView(viewInfo) 169 else: 170 self.LogWarn('Failed to open Contextual Offers window, requested viewType is not supported. Defaulting to confirmation view.') 171 self.wnd.OpenConfirmationView(viewInfo) 172 if isNewWindow: 173 self.wnd.ShowDialog(modal=True, state=uiconst.UI_PICKCHILDREN) 174 175 def _OnWindowOpened(self, offerID, viewType): 176 self.MarkSeenOfferNotification(offerID, OFFER_RECEIVED) 177 178 def _OnWindowClosed(self, offerID, viewType): 179 if viewType == OFFER_RECEIVED: 180 self.TrackOfferClosed(offerID) 181 self.innerService.UnsubscribeFromOfferTimer(offerID, self.wnd) 182 183 def OnBuyClicked(self, offerID): 184 self.audioService.SendUIEvent(SOUND_OFFER_BUY_CLICKED) 185 self.TrackOfferPurchaseClicked(offerID=offerID) 186 self._RedirectToContextualOffersWeb(offerID) 187 188 def _RedirectToContextualOffersWeb(self, offerID): 189 try: 190 offerinfo = self.innerService.GetOfferById(offerID) 191 offerURL = offerinfo['purchaseStep']['PurchaseURL'] 192 uicore.cmd.BuyContextualOfferOnline(offerURL, offerID) 193 except Exception: 194 self.LogException('Failed to direct to purchase URL for the offer (offerID: %s)' % offerID) 195 self._RedirectToSpecialOffersWeb() 196 197 def _RedirectToSpecialOffersWeb(self): 198 try: 199 uicore.cmd.ViewSpecialOffersOnline(origin='contextualofferwindow') 200 except Exception: 201 self.LogException('Failed to direct to Special Offers URL') 202 raise 203 204 def TrackOfferDelivered(self, offerID): 205 sm.RemoteSvc('contextualOfferMgr').TrackOfferDelivered(offerID) 206 207 def TrackOfferIDSeen(self, offerID): 208 sm.RemoteSvc('contextualOfferMgr').TrackOfferSeen(offerID) 209 210 def TrackOfferPurchaseClicked(self, offerID): 211 sm.RemoteSvc('contextualOfferMgr').TrackOfferBuyPress(offerID) 212 213 def TrackOfferClosed(self, offerID): 214 sm.RemoteSvc('contextualOfferMgr').TrackOfferClosed(offerID) 215 216 def TrackOfferPurchased(self, offerID): 217 sm.RemoteSvc('contextualOfferMgr').TrackOfferPurchased(offerID) 218 219 def TrackOfferPurchasedSeen(self, offerID): 220 sm.RemoteSvc('contextualOfferMgr').TrackOfferPurchasedSeen(offerID) 221 222 def Debug_ClearOffers(self): 223 self.innerService.Debug_ClearOffers() 224 self._seenOffersStorage.clear_all() 225 self._neocomOffersNotificationExtension.notify_of_offers_changed() 226 227 def Debug_AddMockOffer1(self): 228 self.OnOfferReceived(1, MockOmegaOfferAvailable()) 229 230 def Debug_AddMockOffer2(self): 231 self.OnOfferReceived(3, MockDestroyerBundleOfferAvailable()) 232 233 def Debug_AddMockOffer3(self): 234 self.OnOfferReceived(4, MockDestroyerBundleAndOmegaOfferAvailable())