def __init__(self): super(CalendarController, self).__init__() self.__browserID = None self.__browserLoaded = False self.__showOnSplash = False self.__urlMacros = URLMarcos() return
def __init__(self, ctx): super(PersonalMissionFirstEntryView, self).__init__(ctx) self.__currentVersionBrowserID = None self.__urlMacros = URLMarcos() self.__settings = GUI_SETTINGS.personalMissions.get('welcomeVideo', {}) self.__cardsLen = len(self.__CARDS) return
class InternalLinksHandler(IInternalLinksController): browserCtrl = dependency.descriptor(IBrowserController) def __init__(self): super(InternalLinksHandler, self).__init__() self.__urlMarcos = None self._browserID = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None self._browserID = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(InternalLinksHandler, self).fini() return @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) @process def __openInternalBrowse(self, urlName, title = '', browserSize = None, showActionBtn = True, showCloseBtn = False): parsedUrl = yield self.getURL(urlName) if parsedUrl: self._browserID = yield self.browserCtrl.load(parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn) def _handleClubHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.CLUB_SIZE) def _handleVideoHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.VIDEO_SIZE, showActionBtn=False, showCloseBtn=True)
class InternalLinksHandler(Controller): def __init__(self, proxy): super(InternalLinksHandler, self).__init__(proxy) self.__urlMarcos = None self._browserID = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None self._browserID = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(InternalLinksHandler, self).fini() return @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) @process def __openInternalBrowse(self, urlName, title = '', browserSize = None, showActionBtn = True, showCloseBtn = False): parsedUrl = yield self.getURL(urlName) if parsedUrl: self._browserID = yield self._proxy.getController(gc_constants.CONTROLLER.BROWSER).load(parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn) def _handleClubHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.CLUB_SIZE) def _handleVideoHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.VIDEO_SIZE, showActionBtn=False, showCloseBtn=True)
def __init__(self, proxy): super(PromoController, self).__init__(proxy) self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self._isPromoShown = False
def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos()
def __init__(self): super(BrowserController, self).__init__() self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return
def __init__(self, data): super(MarathonEvent, self).__init__() self.__data = data self.__isEnabled = False self.__isAvailable = False self.__vehInInventory = False self.__state = '' self.__suspendFlag = False self.__quest = None self.__group = None self.__urlMacros = URLMarcos() self.__baseUrl = GUI_SETTINGS.lookup(data.url) return
def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler)
def __init__(self): super(PromoController, self).__init__() self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self.__guiActionsHandlers = None self.__isLobbyInited = False self.__pendingPromo = None self._isPromoShown = False return
def __init__(self): super(MarathonEventController, self).__init__() self.__isEnabled = False self.__isAvailable = False self.__vehInInventory = False self.__state = '' self.__suspendFlag = False self.__marathonQuest = None self.__marathonGroup = None self.__urlMacros = URLMarcos() self.__baseUrl = GUI_SETTINGS.lookup('marathonUrl') self.__eventManager = Event.EventManager() self.onFlagUpdateNotify = Event.Event(self.__eventManager) return
def showBuyGoldWebOverlay(params=None): url = ingameshop_helpers.getBuyMoreGoldUrl() if url: url = yield URLMarcos().parse(url, params=params) g_eventBus.handleEvent( events.LoadViewEvent(VIEW_ALIAS.OVERLAY_WEB_STORE, ctx={'url': url}), EVENT_BUS_SCOPE.LOBBY)
def __init__(self, _=None): LobbySelectableView.__init__(self, 0) self.__currentCarouselAlias = None self.__isSpaceReadyForC11n = False self.__isVehicleReadyForC11n = False self.__isVehicleCameraReadyForC11n = False self.__urlMacros = URLMarcos() self.__teaser = None return
def __init__(self): super(EncyclopediaController, self).__init__() self.__activated = False self.__recommendations = [] self.__eventManager = Event.EventManager() self.__urlMacros = URLMarcos() self.__isLobbyStarted = False self.__hasNewRecommendations = False if GUI_SETTINGS.lookup('encyclopedia'): self.__baseUrl = GUI_SETTINGS.encyclopedia['url'] self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled'] else: self.__baseUrl = None self.__isSuitableLanguage = False self.onNewRecommendationReceived = Event.Event(self.__eventManager) self.onStateChanged = Event.Event(self.__eventManager) self.__isStateSynced = False return
class PersonalMissionFirstEntryView(LobbySubView, PersonalMissionFirstEntryViewMeta): browserCtrl = dependency.descriptor(IBrowserController) __settingsCore = dependency.descriptor(ISettingsCore) _COMMON_SOUND_SPACE = PERSONAL_MISSIONS_SOUND_SPACE def __init__(self, ctx): super(PersonalMissionFirstEntryView, self).__init__(ctx) self.__currentVersionBrowserID = None self.__urlMacros = URLMarcos() self.__settings = GUI_SETTINGS.personalMissions.get('welcomeVideo', {}) return def playVideo(self): if self.__settings.get('isEnabled', False): self.__showVideo() def backBtnClicked(self): self.__currentVersionBrowserID = None self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS), scope=EVENT_BUS_SCOPE.LOBBY) return def bigBtnClicked(self): self.__settingsCore.serverSettings.setPersonalMissionsFirstEntryState(_FES.TUTORIAL_WAS_SHOWN) self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS), scope=EVENT_BUS_SCOPE.LOBBY) def _populate(self): super(PersonalMissionFirstEntryView, self)._populate() self.as_setInitDataS({'titleLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_TITLE, 'subtitleLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_SUBTITLE, 'bigBtnLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ACKNOWLEDGEBTN, 'playVideoBtnLabel': text_styles.concatStylesToSingleLine(icons.makeImageTag(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_PLAYICON, width=14, height=15, vSpace=-2), i18n.makeString(PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_VIDEOBTNLABEL)), 'playVideoBtnVisible': self.__settings.get('isEnabled', False), 'bgSource': RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_INFOSCREENBG, 'tileList': [self.__makeTileData(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_FREE_SHEET_BIG, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM0_HEADER, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM0_DESCR), self.__makeTileData(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_GEAR_BIG, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM2_HEADER, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM2_DESCR), self.__makeTileData(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_BALANCE, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM1_HEADER, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM1_DESCR)], 'backBtnLabel': PERSONAL_MISSIONS.HEADER_BACKBTN_LABEL, 'isFirstEntry': self.__settingsCore.serverSettings.getPersonalMissionsFirstEntryState() == _FES.NOT_VISITED}) @process def __showVideo(self): url = yield self.__urlMacros.parse(self.__settings.get('url')) webBrowser = self.__getCurrentBrowser() if not webBrowser or url != webBrowser.url: title = i18n.makeString(PERSONAL_MISSIONS.PERSONALMISSIONS_VIDEO_TITLE) self.__currentVersionBrowserID = yield self.browserCtrl.load(url, title, showActionBtn=False, browserID=self.__currentVersionBrowserID, browserSize=gc_constants.BROWSER.VIDEO_SIZE, isDefault=False, showCloseBtn=True, handlers=self.__createWebHandlers()) @staticmethod def __makeTileData(iconSource, titleLabel, descriptionLabel): return {'iconSource': iconSource, 'titleLabel': titleLabel, 'descriptionLabel': descriptionLabel} def __getCurrentBrowser(self): return self.browserCtrl.getBrowser(self.__currentVersionBrowserID) def __createWebHandlers(self): return [createHangarSoundHandler(handleHangarSoundCommand, handleHangarSoundCommandFini)]
def showBuyVehicleOverlay(params=None): url = ingameshop_helpers.getVehicleUrl() if url: url = yield URLMarcos().parse(url, params=params) g_eventBus.handleEvent( events.LoadViewEvent(VIEW_ALIAS.OVERLAY_WEB_STORE, ctx={ 'url': url, 'browserParams': makeBrowserParams(WAITING.BUYITEM, True) }), EVENT_BUS_SCOPE.LOBBY)
def __init__(self): super(PromoController, self).__init__() self.__urlMacros = URLMarcos() self.__externalCloseCallback = None self.__isLobbyInited = False self.__pendingPromo = None self.__promoCount = 0 self.__lastUpdateTimeMark = 0 self.__promoData = None self.__webBrgDataRequested = False self.__battlesFromLastTeaser = 0 self.__wasInBattle = False self.__hasPendingTeaser = False self.__isPromoOpen = False self.__browserCreationCallbacks = {} self.__browserWatchers = {} self.__isInHangar = False self.__isTeaserOpen = False self.__em = EventManager() self.onNewTeaserReceived = Event(self.__em) self.onPromoCountChanged = Event(self.__em) return
def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return
def __init__(self, proxy): super(EncyclopediaController, self).__init__(proxy) self.__activated = False self.__recommendations = [] self.__eventManager = Event.EventManager() self.__urlMacros = URLMarcos() self.__isLobbyStarted = False self.__hasNewRecommendations = False if GUI_SETTINGS.lookup('encyclopedia'): self.__baseUrl = GUI_SETTINGS.encyclopedia['url'] self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled'] else: self.__baseUrl = None self.__isSuitableLanguage = False self.onNewRecommendationReceived = Event.Event(self.__eventManager) self.onStateChanged = Event.Event(self.__eventManager) self.__isStateSynced = False return
class BrowserController(IBrowserController): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self): super(BrowserController, self).__init__() self.__browsers = {} self.__browsersCallbacks = {} self.__browserCreationCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browsersCallbacks.clear() self.__browsersCallbacks = None self.__browsers.clear() self.__browsers = None self.__pendingBrowsers.clear() self.__pendingBrowsers = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def addFilterHandler(self, handler): self.__filters.add(handler) def removeFilterHandler(self, handler): self.__filters.discard(handler) @async @process def load(self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, isDefault=True, callback=None, showCloseBtn=False, useBrowserWindow=True, isModal=False, showCreateWaiting=False, handlers=None, showBrowserCallback=None, isSolidBorder=False): if showCreateWaiting: Waiting.show('browser/init') url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow, 'alias': VIEW_ALIAS.BROWSER_WINDOW_MODAL if isModal else VIEW_ALIAS.BROWSER_WINDOW, 'showCreateWaiting': showCreateWaiting, 'handlers': handlers, 'showBrowserCallback': showBrowserCallback, 'isSolidBorder': isSolidBorder} if browserID not in self.__browsers and browserID not in self.__pendingBrowsers: texture = self._BROWSER_TEXTURE app = g_appLoader.getApp() if app is None: raise SoftException('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): _logger.debug('CTRL: Queueing a browser creation: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: _logger.debug('CTRL: Re-queuing a browser creation, overriding: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: _logger.debug('CTRL: Re-navigating an existing browser: %r - %s', browserID, url) browser = self.__browsers[browserID] browser.navigate(url) browser.changeTitle(title) callback(browserID) return def getAllBrowsers(self): return self.__browsers def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: _logger.debug('CTRL: Deleting a browser: %s', browserID) browser = self.__browsers.pop(browserID) self.__clearCallbacks(browserID, browser, True) browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() if browserID in self.__pendingBrowsers: del self.__pendingBrowsers[browserID] self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): _logger.debug('CTRL: Finished creating a browser: %s', self.__creatingBrowserID) if ctx['showCreateWaiting']: Waiting.hide('browser/init') def __tryCreateNextPendingBrowser(self): self.__creatingBrowserID = None if self.__pendingBrowsers: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) return def __createBrowser(self, ctx): browserID = ctx['browserID'] _logger.debug('CTRL: Creating a browser: %r - %s', browserID, ctx['url']) self.__creatingBrowserID = browserID browser = self.__browsers[browserID] if not browser.create(): _logger.debug('CTRL: Failed the create step: %r', browserID) self.delBrowser(browserID) self.__tryCreateNextPendingBrowser() return else: self.onBrowserAdded(browserID) def createBrowserTimeout(): _logger.debug('CTRL: Browser create timed out') createNextBrowser() timeoutid = BigWorld.callback(30.0, createBrowserTimeout) def createNextBrowser(): _logger.debug('CTRL: Triggering create of next browser from: %s', browserID) BigWorld.cancelCallback(timeoutid) creation = self.__browserCreationCallbacks.pop(browserID, None) if creation is not None: self.__browsers[browserID].onCanCreateNewBrowser -= creation BigWorld.callback(1.0, self.__tryCreateNextPendingBrowser) return def failedCreationCallback(url): _logger.debug('CTRL: Failed a creation: %r - %s', browserID, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) self.delBrowser(browserID) def successfulCreationCallback(url, isLoaded, httpStatusCode=None): _logger.debug('CTRL: Ready to show: %r - %r - %s', browserID, isLoaded, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) if isLoaded: self.__showBrowser(browserID, ctx) else: _logger.warning('Browser request url %s was not loaded!', url) g_eventBus.handleEvent(BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__createDone(ctx) def titleUpdateCallback(title): ctx['title'] = title browser.onCanCreateNewBrowser += createNextBrowser self.__browserCreationCallbacks[browserID] = createNextBrowser browser.onFailedCreation += failedCreationCallback browser.onTitleChange += titleUpdateCallback if ctx['isAsync']: self.__browsersCallbacks[browserID] = (None, successfulCreationCallback, failedCreationCallback, titleUpdateCallback) browser.onLoadEnd += successfulCreationCallback else: self.__browsersCallbacks[browserID] = (successfulCreationCallback, None, failedCreationCallback, titleUpdateCallback) browser.onReady += successfulCreationCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() self.__clearCallbacks(browserID, browser, True) browser.destroy() def __clearCallbacks(self, browserID, browser, incDelayedCreation): ready, loadEnd, failed, title = self.__browsersCallbacks.pop(browserID, (None, None, None, None)) if browser is not None: if failed is not None: browser.onFailedCreation -= failed if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd if title is not None: browser.onTitleChange -= title if incDelayedCreation: creation = self.__browserCreationCallbacks.pop(browserID, None) if browser is not None and creation is not None: browser.onCanCreateNewBrowser -= creation return def __showBrowser(self, browserID, ctx): _logger.debug('CTRL: Showing a browser: %r - %s', browserID, ctx['url']) if ctx.get('showWindow'): alias = ctx['alias'] g_eventBus.handleEvent(LoadViewEvent(alias, getViewName(alias, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY) showBrowserCallback = ctx.get('showBrowserCallback') if showBrowserCallback: showBrowserCallback()
class PromoController(Controller): PROMO_AUTO_VIEWS_TEST_VALUE = 5 def __init__(self, proxy): super(PromoController, self).__init__(proxy) self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self._isPromoShown = False return def fini(self): self._stop() self.__urlMacros.clear() self.__urlMacros = None super(PromoController, self).fini() return def onLobbyInited(self, event): self._updatePromo(self._getPromoEventNotifications()) self._getEventsFotificationController().onEventNotificationsChanged += self.__onEventNotification self._getBrowserController().onBrowserDeleted += self.__onBrowserDeleted self._processPromo(self._getEventNotifications()) def onAvatarBecomePlayer(self): self._stop() def onDisconnected(self): self._stop() self._isPromoShown = False @process def showPatchPromo(self, isAsync = False): self.__currentVersionBrowserID = yield self.__showPromoBrowser(self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE, version=getClientVersion()), browserID=self.__currentVersionBrowserID, isAsync=isAsync) def isPatchPromoAvailable(self): return self.__currentVersionPromoUrl is not None def _stop(self): self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self._getBrowserController().onBrowserDeleted -= self.__onBrowserDeleted self._getEventsFotificationController().onEventNotificationsChanged -= self.__onEventNotification return @process def _processPromo(self, promo): yield lambda callback: callback(True) if self.isPatchPromoAvailable() and self.__currentVersionPromoUrl not in self.__promoShown and self.isPromoAutoViewsEnabled() and not self._isPromoShown: LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl) self.__promoShown.add(self.__currentVersionPromoUrl) self.__savePromoShown() self.__currentVersionBrowserShown = True self._isPromoShown = True self.showPatchPromo(isAsync=True) return actionsPromo = [ item for item in promo if item.eventType.startswith(gc_constants.PROMO.TEMPLATE.ACTION) ] for actionPromo in actionsPromo: promoUrl = yield self.__urlMacros.parse(actionPromo.data) promoTitle = actionPromo.text if promoUrl not in self.__promoShown and not self._isPromoShown: LOG_DEBUG('Showing action promo:', promoUrl) self.__promoShown.add(promoUrl) self.__savePromoShown() self._isPromoShown = True yield self.__showPromoBrowser(promoUrl, promoTitle) return @process def _updatePromo(self, promosData): yield lambda callback: callback(True) for item in filter(lambda item: item.eventType in (gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE.ACTION), promosData): promoUrl = yield self.__urlMacros.parse(item.data) self.__availablePromo.add(promoUrl) if item.eventType == gc_constants.PROMO.TEMPLATE.PATCH and self.__currentVersionPromoUrl is None: self.__currentVersionPromoUrl = promoUrl promoShownSource = AccountSettings.getFilter(PROMO) self.__promoShown = {url for url in promoShownSource if url in self.__availablePromo} self.__savePromoShown() return def _getEventNotifications(self): return self._proxy.getController(gc_constants.CONTROLLER.EVENTS_NOTIFICATION).getEventsNotifications() def _getPromoEventNotifications(self): filterFunc = lambda item: item.eventType in (gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE.ACTION) return self._getEventsFotificationController().getEventsNotifications(filterFunc) def _getBrowserController(self): return self._proxy.getController(gc_constants.CONTROLLER.BROWSER) def _getEventsFotificationController(self): return self._proxy.getController(gc_constants.CONTROLLER.EVENTS_NOTIFICATION) def __savePromoShown(self): AccountSettings.setFilter(PROMO, self.__promoShown) def __onEventNotification(self, added, removed): self._updatePromo(self._getPromoEventNotifications()) self._processPromo(added) def __onBrowserDeleted(self, browserID): if self.__currentVersionBrowserID == browserID: self.__currentVersionBrowserID = None if self.__currentVersionBrowserShown: self.__currentVersionBrowserShown = False g_eventBus.handleEvent(events.BubbleTooltipEvent(events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY) return @async @process def __showPromoBrowser(self, promoUrl, promoTitle, browserID = None, isAsync = True, callback = None): browserID = yield self._getBrowserController().load(promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, background=gc_constants.BROWSER.PROMO_BACKGROUND, isDefault=False, showCloseBtn=True) callback(browserID) @classmethod def isPromoAutoViewsEnabled(cls): return getAccountDatabaseID() % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and g_lobbyContext.getServerSettings().isPromoAutoViewsEnabled()
class PromoController(IPromoController): browserCtrl = dependency.descriptor(IBrowserController) eventsNotification = dependency.descriptor(IEventsNotificationsController) __webController = dependency.descriptor(IWebController) __settingsCore = dependency.descriptor(ISettingsCore) __lobbyContext = dependency.descriptor(ILobbyContext) __logger = dependency.descriptor(IPromoLogger) __bootcamp = dependency.descriptor(IBootcampController) _CHECK_FREQUENCY_IN_BATTLES = 10 def __init__(self): super(PromoController, self).__init__() self.__urlMacros = URLMarcos() self.__externalCloseCallback = None self.__isLobbyInited = False self.__pendingPromo = None self.__promoCount = 0 self.__lastUpdateTimeMark = 0 self.__promoData = None self.__webBrgDataRequested = False self.__battlesFromLastTeaser = 0 self.__wasInBattle = False self.__hasPendingTeaser = False self.__isPromoOpen = False self.__browserCreationCallbacks = {} self.__browserWatchers = {} self.__isInHangar = False self.__isTeaserOpen = False self.__em = EventManager() self.onNewTeaserReceived = Event(self.__em) self.onPromoCountChanged = Event(self.__em) return @sf_lobby def app(self): pass def fini(self): self.__stop() self.__pendingPromo = None self.__urlMacros.clear() self.__urlMacros = None self.__externalCloseCallback = None self.__em.clear() g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__browserCreationCallbacks = {} self.__browserWatchers = {} super(PromoController, self).fini() return def onLobbyInited(self, event): if not isPlayerAccount(): return g_eventBus.addListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__isLobbyInited = True if self.__hasPendingTeaser: self.__tryToShowTeaser() elif self.__battlesFromLastTeaser % self._CHECK_FREQUENCY_IN_BATTLES == 0: self.__updateWebBrgData() self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification if not isPopupsWindowsOpenDisabled(): self.__processPromo( self.eventsNotification.getEventsNotifications()) self.app.loaderManager.onViewLoaded += self.__onViewLoaded def setNewTeaserData(self, teaserData): timestamp = teaserData['timestamp'] if self.__lastUpdateTimeMark < timestamp and not self.__isPromoOpen and not self.__isTeaserOpen: self.__updateTeaserData(teaserData) def showFieldPost(self): url = GUI_SETTINGS.promoscreens loadingCallback = self.__logger.getLoggingFuture( action=PromoLogActions.OPEN_FROM_MENU, type=PromoLogSubjectType.INDEX, url=url) self.__showBrowserView(url, loadingCallback) @process def showLastTeaserPromo(self): rowUrl = self.__promoData.get('url', '') loadingCallback = self.__logger.getLoggingFuture( self.__promoData, action=PromoLogActions.OPEN_FROM_TEASER, type=PromoLogSubjectType.PROMO_SCREEN, url=rowUrl) url = yield self.__addAuthParams(rowUrl) self.__showBrowserView(url, loadingCallback) def setUnreadPromoCount(self, count): self.__updatePromoCount(count) def onAvatarBecomePlayer(self): if self.__isLobbyInited: self.__battlesFromLastTeaser += 1 self.__stop() def onDisconnected(self): self.__stop() def isActive(self): return self.__lobbyContext.getServerSettings().isFieldPostEnabled( ) and not self.__bootcamp.isInBootcamp() def getPromoCount(self): return self.__promoCount def showPromo(self, url, closeCallback=None, source=None): if self.__isLobbyInited: if not self.__isPromoOpen and not self.__webBrgDataRequested: self.__registerAndShowPromoBrowser( url, closeCallback, self.__logger.getLoggingFuture( action=PromoLogActions.OPEN_IN_OLD, type=PromoLogSubjectType.PROMO_SCREEN, source=source, url=url)) else: self.__pendingPromo = _PromoData(url, closeCallback, source) def __onTeaserClosed(self, byUser=False): self.__isTeaserOpen = False if byUser: self.__showBubbleTooltip() def __showBubbleTooltip(self): storageData = self.__settingsCore.serverSettings.getUIStorage() if not storageData.get(UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN): showBubbleTooltip(i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)) self.__settingsCore.serverSettings.saveInUIStorage( {UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN: True}) @process def __updateWebBrgData(self): ctx = PromoGetTeaserRequestCtx() if self.__battlesFromLastTeaser == 0: sourceType = PromoLogSourceType.FIRST_LOGIN else: sourceType = PromoLogSourceType.AFTER_BATTLE answerCallback = self.__logger.getLoggingFuture( action=PromoLogActions.GET_MOST_IMPORTANT, source=sourceType) self.__webBrgDataRequested = True response = yield self.__webController.sendRequest(ctx=ctx) if response.isSuccess(): self.__updateTeaserData(ctx.getDataObj(response.getData())) self.__webBrgDataRequested = False if answerCallback: answerCallback(success=response.extraCode) def __onPromoClosed(self, **kwargs): self.__isPromoOpen = False self.__showBubbleTooltip() if self.__externalCloseCallback: self.__externalCloseCallback() self.__requestPromoCount() actionType = PromoLogActions.CLOSED_BY_USER if kwargs.get( 'byUser') else PromoLogActions.KILLED_BY_SYSTEM self.__logger.logAction(action=actionType, type=PromoLogSubjectType.PROMO_SCREEN_OR_INDEX, url=kwargs.get('url')) @process def __requestPromoCount(self): if not self.isActive(): _logger.warning( 'Trying to request unread promos count when promo functionality is disabled' ) return ctx = PromoGetUnreadCountRequestCtx() response = yield self.__webController.sendRequest(ctx=ctx) if response.isSuccess(): self.__updatePromoCount(ctx.getCount(response)) def __updatePromoCount(self, count): countChanged = count != self.__promoCount self.__promoCount = count if countChanged: self.onPromoCountChanged() def __updateTeaserData(self, teaserData): self.__lastUpdateTimeMark = teaserData['timestamp'] self.__promoData = teaserData['lastPromo'] self.__updatePromoCount(teaserData['count']) if self.__promoData.get('url'): self.__tryToShowTeaser() def __showTeaser(self): if self.isActive(): self.__battlesFromLastTeaser = 0 self.__hasPendingTeaser = False self.onNewTeaserReceived(self.__promoData, self.__onTeaserShown, self.__onTeaserClosed) else: _logger.warning( 'Impossible to show teaser, functionality is disabled') @process def __onTeaserShown(self, promoID): self.__isTeaserOpen = True yield self.__webController.sendRequest( PromoSendTeaserShownRequestCtx(promoID)) def __tryToShowTeaser(self): if self.__isLobbyInited and self.__isInHangar: self.__showTeaser() else: self.__hasPendingTeaser = True def __stop(self): if self.app and self.app.loaderManager: self.app.loaderManager.onViewLoaded -= self.__onViewLoaded self.__isLobbyInited = False self.__isPromoOpen = False self.__currentVersionBrowserID = None self.__externalCloseCallback = None self.__isTeaserOpen = False self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__browserCreationCallbacks = {} watcherKeys = self.__browserWatchers.keys() for browserID in watcherKeys: self.__clearWatcher(browserID) return def __processPromo(self, promos): if not self.__isPromoOpen and not self.__webBrgDataRequested: logData = { 'action': PromoLogActions.OPEN_IN_OLD, 'type': PromoLogSubjectType.PROMO_SCREEN } if self.__pendingPromo is not None: promoData = self.__pendingPromo logData.update({ 'source': promoData.source, 'url': promoData.url }) loadingCallback = self.__logger.getLoggingFuture(**logData) self.__registerAndShowPromoBrowser(promoData.url, promoData.closeCallback, loadingCallback) self.__pendingPromo = None return promo = findFirst( lambda item: item.eventType.startswith( gc_constants.PROMO.TEMPLATE.ACTION), promos) if promo: logData.update({ 'source': PromoLogSourceType.SSE, 'url': promo.data }) self.__showBrowserView( promo.data, self.__logger.getLoggingFuture(**logData)) return def __onEventNotification(self, added, _): self.__processPromo(added) def __registerAndShowPromoBrowser(self, url, closeCallback, loadingCallback): self.__externalCloseCallback = closeCallback self.__showBrowserView(url, loadingCallback) @process def __showBrowserView(self, url, loadingCallback=None): promoUrl = yield self.__urlMacros.parse(url) self.__registerLoadingCallback(promoUrl, loadingCallback) _showBrowserView(promoUrl, self.__onPromoClosed) self.__isPromoOpen = True def __registerLoadingCallback(self, url, callback): if callback is not None: self.__browserCreationCallbacks[url] = callback return def __handleBrowserCreated(self, event): url = event.ctx.get('url') if url in self.__browserCreationCallbacks: callback = self.__browserCreationCallbacks.pop(url) browserID = event.ctx.get('browserID') browser = self.browserCtrl.getBrowser(browserID) if browser is None: return def callbackWrapper(clbUrl, _, statusCode): if clbUrl == url: callback(url=url, success=statusCode) self.__clearWatcher(browserID) browser.onLoadEnd += callbackWrapper self.__browserWatchers[browserID] = callbackWrapper return def __clearWatcher(self, browserID): if browserID in self.__browserWatchers: watcher = self.__browserWatchers.pop(browserID) browser = self.browserCtrl.getBrowser(browserID) if browser is not None: browser.onLoadEnd -= watcher return @async @process def __addAuthParams(self, url, callback): if not url or not self.__webController: callback(url) accessTokenData = yield self.__webController.getAccessTokenData( force=True) params = { 'access_token': str(accessTokenData.accessToken), 'spa_id': BigWorld.player().databaseID } callback(url_formatters.addParamsToUrlQuery(url, params)) def __onViewLoaded(self, pyView, _): if self.__isLobbyInited: if pyView.alias == VIEW_ALIAS.LOBBY_HANGAR: self.__isInHangar = True if self.__hasPendingTeaser: self.__tryToShowTeaser() elif pyView.viewType == ViewTypes.LOBBY_SUB: self.__isInHangar = False
class BrowserController(IBrowserController): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self): super(BrowserController, self).__init__() self.__browsers = {} self.__browsersCallbacks = {} self.__browserCreationCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browsersCallbacks.clear() self.__browsersCallbacks = None self.__browsers.clear() self.__browsers = None self.__pendingBrowsers.clear() self.__pendingBrowsers = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def addFilterHandler(self, handler): """ Adds given @handler to the browser urls filter chain. Calls it if there is a @tag in url onto opened browser page. Handler should receive url and list of client-specific tags, return bool as flag that routine have to stop """ self.__filters.add(handler) def removeFilterHandler(self, handler): """ Remove given @handler from filtering chain. Handler description can be seen in addFilterhandler method doc-string """ self.__filters.discard(handler) @async @process def load(self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, isDefault=True, callback=None, showCloseBtn=False, useBrowserWindow=True, isModal=False, showCreateWaiting=False, handlers=None, showBrowserCallback=None, isSolidBorder=False): if constants.IS_BOOTCAMP_ENABLED: from bootcamp.Bootcamp import g_bootcamp if g_bootcamp.isRunning(): return if showCreateWaiting: Waiting.show('browser/init') url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = { 'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow, 'alias': VIEW_ALIAS.BROWSER_WINDOW_MODAL if isModal else VIEW_ALIAS.BROWSER_WINDOW, 'showCreateWaiting': showCreateWaiting, 'handlers': handlers, 'showBrowserCallback': showBrowserCallback, 'isSolidBorder': isSolidBorder } texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and self._BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): LOG_BROWSER('CTRL: Queueing a browser creation: ', browserID, url) self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: LOG_BROWSER('CTRL: Re-queuing a browser creation, overriding: ', browserID, url) self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: LOG_BROWSER('CTRL: Re-navigating an existing browser: ', browserID, url) browser = self.__browsers[browserID] browser.navigate(url) browser.changeTitle(title) callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: LOG_BROWSER('CTRL: Deleting a browser: ', browserID) browser = self.__browsers.pop(browserID) self.__clearCallbacks(browserID, browser, True) browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() if browserID in self.__pendingBrowsers: del self.__pendingBrowsers[browserID] self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): LOG_BROWSER('CTRL: Finished creating a browser: ', self.__creatingBrowserID) if ctx['showCreateWaiting']: Waiting.hide('browser/init') def __tryCreateNextPendingBrowser(self): self.__creatingBrowserID = None if len(self.__pendingBrowsers) > 0: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) return def __createBrowser(self, ctx): browserID = ctx['browserID'] LOG_BROWSER('CTRL: Creating a browser: ', browserID, ctx['url']) self.__creatingBrowserID = browserID if not self.__browsers[browserID].create(): LOG_BROWSER('CTRL: Failed the create step: ', browserID) self.delBrowser(browserID) self.__tryCreateNextPendingBrowser() return else: self.onBrowserAdded(browserID) def createBrowserTimeout(): LOG_BROWSER('CTRL: Browser create timed out') createNextBrowser() timeoutid = BigWorld.callback(30.0, createBrowserTimeout) def createNextBrowser(): LOG_BROWSER('CTRL: Triggering create of next browser from: ', browserID) BigWorld.cancelCallback(timeoutid) creation = self.__browserCreationCallbacks.pop(browserID, None) if creation is not None: self.__browsers[ browserID].onCanCreateNewBrowser -= creation BigWorld.callback(1.0, self.__tryCreateNextPendingBrowser) return def failedCreationCallback(url): LOG_BROWSER('CTRL: Failed a creation: ', browserID, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) self.delBrowser(browserID) def successfulCreationCallback(url, isLoaded, httpStatusCode=None): LOG_BROWSER('CTRL: Ready to show: ', browserID, isLoaded, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser request url was not loaded!', url) g_eventBus.handleEvent( BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__createDone(ctx) self.__browsers[ browserID].onCanCreateNewBrowser += createNextBrowser self.__browserCreationCallbacks[browserID] = createNextBrowser self.__browsers[ browserID].onFailedCreation += failedCreationCallback if ctx['isAsync']: self.__browsersCallbacks[browserID] = ( None, successfulCreationCallback, failedCreationCallback) self.__browsers[ browserID].onLoadEnd += successfulCreationCallback else: self.__browsersCallbacks[browserID] = ( successfulCreationCallback, None, failedCreationCallback) self.__browsers[ browserID].onReady += successfulCreationCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() self.__clearCallbacks(browserID, browser, True) browser.destroy() def __clearCallbacks(self, browserID, browser, incDelayedCreation): ready, loadEnd, failed = self.__browsersCallbacks.pop( browserID, (None, None, None)) if browser is not None: if failed is not None: browser.onFailedCreation -= failed if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd if incDelayedCreation: creation = self.__browserCreationCallbacks.pop(browserID, None) if browser is not None and creation is not None: browser.onCanCreateNewBrowser -= creation return def __showBrowser(self, browserID, ctx): LOG_BROWSER('CTRL: Showing a browser: ', browserID, ctx['url']) if ctx.get('showWindow'): alias = ctx['alias'] g_eventBus.handleEvent( LoadViewEvent(alias, getViewName(alias, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY) showBrowserCallback = ctx.get('showBrowserCallback') if showBrowserCallback: showBrowserCallback()
class RssNewsFeed(RssNewsFeedMeta): UPDATE_INTERVAL = 60 DESCRIPTION_MAX_LENGTH = 250 DESCRIPTION_TAIL = '...' DESCRIPTION_CUT_LENGTH = DESCRIPTION_MAX_LENGTH - len(DESCRIPTION_TAIL) SHOW_NEWS_COUNT = 3 externalBrowser = dependency.descriptor(IExternalLinksController) internalBrowser = dependency.descriptor(IBrowserController) def __init__(self): super(RssNewsFeed, self).__init__() self.__requestCbID = None self.__feed = [] self.__urlMacros = URLMarcos() return def getFeed(self): return self.__feed def openBrowser(self, linkToOpen): if linkToOpen: openBrowser = self.externalBrowser.open if GUI_SETTINGS.loginRssFeed.internalBrowser: browser = self.internalBrowser if browser is not None: openBrowser = browser.load else: LOG_ERROR( 'Attempting to open internal browser, but browseris not exist. External browser will be opened', str(linkToOpen)) LOG_DEBUG('Open browser', linkToOpen) openBrowser(linkToOpen) return def _populate(self): super(RssNewsFeed, self)._populate() self.__updateCallback() def _dispose(self): self.__urlMacros.clear() self.__urlMacros = None self.__feed = [] self.__clearCallback() super(RssNewsFeed, self)._dispose() return @process def __requestFeed(self): yield lambda callback: callback(True) if GUI_SETTINGS.loginRssFeed.show: requestUrl = yield self.__getRssUrl() from helpers.RSSDownloader import g_downloader as g_rss if g_rss is not None: g_rss.download(self.__onRssFeedReceived, url=requestUrl) LOG_DEBUG('Requesting login RSS news', requestUrl) return def __onRssFeedReceived(self, data): if self.isDisposed(): return else: self.__feed = [] for entry in reversed(data.get('entries', [])): data = self.__prepareData(entry) if data is not None: self.__feed.append(data) LOG_DEBUG('RSS feed received, entries count', len(self.__feed)) self.as_updateFeedS(self.__feed[:self.SHOW_NEWS_COUNT]) return def __clearCallback(self): if self.__requestCbID is not None: BigWorld.cancelCallback(self.__requestCbID) self.__requestCbID = None return def __updateCallback(self): self.__requestFeed() self.__clearCallback() self.__requestCbID = BigWorld.callback(self.UPDATE_INTERVAL, self.__updateCallback) @async @process def __getRssUrl(self, callback): if constants.IS_CHINA: callback('http://wot.kongzhong.com/erji/login_ticker.xml') url = yield self.__urlMacros.parse(str(GUI_SETTINGS.loginRssFeed.url)) callback(url) def __prepareData(self, entryData): description = entryData.get('description') if description is not None: try: section = ResMgr.DataSection() section.createSectionFromString(encodeUtf8(description)) _, section = findFirst(lambda (name, _): name == 'div', section.items()) description, _ = unicode_from_utf8(section.asString) if len(description) > self.DESCRIPTION_MAX_LENGTH: description = description[:self. DESCRIPTION_CUT_LENGTH] + self.DESCRIPTION_TAIL except Exception: LOG_ERROR('Invalid RSS entry description', entryData, description) LOG_CURRENT_EXCEPTION() return return { 'id': entryData.get('id', str(uuid.uuid4())), 'link': entryData.get('link'), 'description': encodeUtf8(description) }
class BrowserController(Controller): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def addFilterHandler(self, handler): """ Adds given @handler to the browser urls filter chain. Calls it if there is a @tag in url onto opened browser page. Handler should receive url and list of client-specific tags, return bool as flag that routine have to stop """ self.__filters.add(handler) def removeFilterHandler(self, handler): """ Remove given @handler from filtering chain. Handler description can be seen in addFilterhandler method doc-string """ self.__filters.discard(handler) @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False, useBrowserWindow = True): url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow} texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and self._BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: self.__browsers[browserID].navigate(url) callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): self.__creatingBrowserID = None g_eventBus.handleEvent(BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__tryCreateNextPendingBrowser() return def __tryCreateNextPendingBrowser(self): if len(self.__pendingBrowsers) > 0: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) def __createBrowser(self, ctx): browserID = ctx['browserID'] self.__creatingBrowserID = browserID self.__browsers[browserID].create() self.onBrowserAdded(browserID) def browserCallback(url, isLoaded): self.__clearCallback(browserID) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser request url was not loaded!', url) self.__createDone(browserID) if ctx['isAsync']: self.__browsersCallbacks[browserID] = (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onReady += browserCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: self.__browsers[browserID].onReady -= ready if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): if ctx.get('showWindow'): g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class PromoController(IPromoController): PROMO_AUTO_VIEWS_TEST_VALUE = 5 browserCtrl = dependency.descriptor(IBrowserController) eventsNotification = dependency.descriptor(IEventsNotificationsController) lobbyContext = dependency.descriptor(ILobbyContext) class GUI_EVENTS(CONST_CONTAINER): CLOSE_GUI_EVENT = 'close_window' def __init__(self): super(PromoController, self).__init__() self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self.__guiActionsHandlers = None self.__isLobbyInited = False self.__pendingPromo = None self._isPromoShown = False return def fini(self): self._stop() self.__pendingPromo = None self.__urlMacros.clear() self.__urlMacros = None self.__guiActionsHandlers = None super(PromoController, self).fini() return def onLobbyInited(self, event): if not isPlayerAccount(): return self.__isLobbyInited = True self._updatePromo(self._getPromoEventNotifications()) self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted popupsWindowsDisabled = isPopupsWindowsOpenDisabled() if not popupsWindowsDisabled: self._processPromo( self.eventsNotification.getEventsNotifications()) def onAvatarBecomePlayer(self): self._stop() def onDisconnected(self): self._stop() self._isPromoShown = False @process def showVersionsPatchPromo(self): promoUrl = yield self.__urlMacros.parse(GUI_SETTINGS.promoscreens) webBrowser = self.__getCurrentBrowser() if not webBrowser or promoUrl != webBrowser.url: promoTitle = i18n.makeString(MENU.PROMO_PATCH_TITLE) self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, promoTitle, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) def showPromo(self, url, title, forced=False, handlers=None): """ :param url: url that should be opened in the browser: :param title: the title of browser window: :param forced: True - promowindow with new URL will be shown in any case, False - new promowindow will be shown if there has not been already shown promowindow during the session: :param handlers: Dict: key - gui action self.GUI_EVENTS.* value - functions that should to be invoked when particular gui action has happened """ if forced: self.__registerAndShowPromoBrowser(url, title, handlers) self._isPromoShown = True elif self.__isLobbyInited: if not self._isPromoShown: self.__registerAndShowPromoBrowser(url, title, handlers) self._isPromoShown = True else: self.__pendingPromo = _PromoData(url, title, handlers) def getCurrentVersionBrowserID(self): return self.__currentVersionBrowserID @classmethod def isPromoAutoViewsEnabled(cls): return getAccountDatabaseID( ) % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and cls.lobbyContext.getServerSettings( ).isPromoAutoViewsEnabled() def isPatchPromoAvailable(self): return self.__currentVersionPromoUrl is not None and GUI_SETTINGS.isPatchPromoEnabled def isPatchChanged(self): mainVersion = getClientMainVersion() return mainVersion is not None and AccountSettings.getSettings( LAST_PROMO_PATCH_VERSION) != mainVersion def _stop(self): self.__isLobbyInited = False self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted self.__cleanupGuiActionHandlers() self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification return @process def _showCurrentVersionPatchPromo(self, isAsync=False): self.__currentVersionBrowserID = yield self.__showPromoBrowser( self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE), browserID=self.__currentVersionBrowserID, isAsync=isAsync, showWaiting=not isAsync) @process def _processPromo(self, promo): yield lambda callback: callback(True) if self.isPatchPromoAvailable() and self.isPatchChanged( ) and self.isPromoAutoViewsEnabled() and not self._isPromoShown: LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl) AccountSettings.setSettings(LAST_PROMO_PATCH_VERSION, getClientMainVersion()) self.__currentVersionBrowserShown = True self._isPromoShown = True self._showCurrentVersionPatchPromo(isAsync=True) return elif not self._isPromoShown and self.__pendingPromo is not None: self.__registerAndShowPromoBrowser(*self.__pendingPromo) self.__pendingPromo = None return else: actionsPromo = [ item for item in promo if item.eventType.startswith( gc_constants.PROMO.TEMPLATE.ACTION) ] for actionPromo in actionsPromo: promoUrl = yield self.__urlMacros.parse(actionPromo.data) promoTitle = actionPromo.text if promoUrl not in self.__promoShown and not self._isPromoShown and promoUrl != self.__currentVersionPromoUrl: LOG_DEBUG('Showing action promo:', promoUrl) self.__promoShown.add(promoUrl) self.__savePromoShown() self._isPromoShown = True yield self.__showPromoBrowser(promoUrl, promoTitle) return return @process def _updatePromo(self, promosData): yield lambda callback: callback(True) for item in filter( lambda item: item.eventType == gc_constants.PROMO.TEMPLATE. ACTION, promosData): promoUrl = yield self.__urlMacros.parse(item.data) self.__availablePromo.add(promoUrl) if self.__currentVersionPromoUrl is None: self.__currentVersionPromoUrl = yield self.__urlMacros.parse( GUI_SETTINGS.currentVersionPromo) promoShownSource = AccountSettings.getFilter(PROMO) self.__promoShown = { url for url in promoShownSource if url in self.__availablePromo } self.__savePromoShown() return def _getPromoEventNotifications(self): def filterFunc(item): return item.eventType == gc_constants.PROMO.TEMPLATE.ACTION return self.eventsNotification.getEventsNotifications(filterFunc) def __onUserRequestToClose(self): self.__guiActionsHandlers[self.GUI_EVENTS.CLOSE_GUI_EVENT]() self.__cleanupGuiActionHandlers() def __savePromoShown(self): AccountSettings.setFilter(PROMO, self.__promoShown) def __onEventNotification(self, added, removed): self._updatePromo(self._getPromoEventNotifications()) self._processPromo(added) def __onBrowserDeleted(self, browserID): if self.__currentVersionBrowserID == browserID: self.__currentVersionBrowserID = None if self.__currentVersionBrowserShown: self.__currentVersionBrowserShown = False g_eventBus.handleEvent(events.BubbleTooltipEvent( events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY) return def __registerGuiActionHandlers(self, handlers): self.__guiActionsHandlers = handlers if handlers: webBrowser = self.__getCurrentBrowser() if webBrowser is not None: webBrowser.onUserRequestToClose += self.__onUserRequestToClose else: LOG_WARNING('Browser with id = "{}" has not been found'.format( self.__currentVersionBrowserID)) return def __cleanupGuiActionHandlers(self): webBrowser = self.__getCurrentBrowser() if self.__guiActionsHandlers is not None and webBrowser: webBrowser.onUserRequestToClose -= self.__onUserRequestToClose self.__guiActionsHandlers = None return @process def __registerAndShowPromoBrowser(self, url, title, handlers): promoUrl = yield self.__urlMacros.parse(url) LOG_DEBUG('Showing promo:', promoUrl) webBrowser = self.__getCurrentBrowser() if not webBrowser or promoUrl != webBrowser.url: self.__cleanupGuiActionHandlers() self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, title, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) self.__registerGuiActionHandlers(handlers) def __getCurrentBrowser(self): return self.browserCtrl.getBrowser(self.__currentVersionBrowserID) @async @process def __showPromoBrowser(self, promoUrl, promoTitle, browserID=None, isAsync=True, showWaiting=False, callback=None): browserID = yield self.browserCtrl.load( promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, isDefault=False, showCloseBtn=True, showWaiting=showWaiting, handlers=self.__createPromoWebHandlers()) callback(browserID) def __createPromoWebHandlers(self): return [ createHangarSoundHandler(handleHangarSoundCommand, handleHangarSoundCommandFini) ]
class BrowserController(Controller): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False): url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE if browserID is None: browserID = self.__browserIDGenerator.next() if browserID not in self.__browsers: texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') self.__browsers[browserID] = WebBrowser(browserID, app, texture, size, url) self.onBrowserAdded(browserID) ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isDefault': isDefault, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn} def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) def browserAsyncCallback(url, isLoaded): self.__clearCallback(browserID) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser async request url was not loaded!', url) self.__browsersCallbacks[browserID] = isAsync and (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserAsyncCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onLoadStart += browserCallback callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): if browserID in self.__browsersCallbacks: loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: self.__browsers[browserID].onLoadStart -= loadStart if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class BrowserController(Controller): _BROWSER_TEXTURE = "BrowserBg" _ALT_BROWSER_TEXTURE = "AltBrowserBg" def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load( self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, background=None, isDefault=True, callback=None, showCloseBtn=False, ): url = url or GUI_SETTINGS.browser.url suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = "&" if "?" in url else "?" if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE background = background or BROWSER.BACKGROUND if browserID is None: browserID = self.__browserIDGenerator.next() if browserID not in self.__browsers: texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError("Application can not be None") self.__browsers[browserID] = WebBrowser(browserID, app, texture, size, url, backgroundUrl=background) self.onBrowserAdded(browserID) ctx = { "url": url, "title": title, "showActionBtn": showActionBtn, "showWaiting": showWaiting, "browserID": browserID, "size": size, "isDefault": isDefault, "isAsync": isAsync, "showCloseBtn": showCloseBtn, } def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) self.__browsersCallbacks[browserID] = isAsync and (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onLoadStart += browserCallback callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): if browserID in self.__browsersCallbacks: loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: self.__browsers[browserID].onLoadStart -= loadStart if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): g_eventBus.handleEvent( LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY, )
class MarathonEvent(object): _eventsCache = dependency.descriptor(IEventsCache) _bootcamp = dependency.descriptor(IBootcampController) def __init__(self, data): super(MarathonEvent, self).__init__() self.__data = data self.__isEnabled = False self.__isAvailable = False self.__vehInInventory = False self.__state = '' self.__suspendFlag = False self.__quest = None self.__group = None self.__urlMacros = URLMarcos() self.__baseUrl = GUI_SETTINGS.lookup(data.url) return @property def prefix(self): return self.__data.prefix @property def data(self): return self.__data @prbEntityProperty def prbEntity(self): return None @async @process def getUrl(self, callback): if self.__baseUrl is None: LOG_ERROR( 'Requesting URL for marathon when base URL is not specified') yield lambda clb: clb(None) else: url = yield self.__urlMacros.parse(self.__baseUrl) callback(url) return def isEnabled(self): return self.__isEnabled and not self._bootcamp.isInBootcamp() def isAvailable(self): return self.__isAvailable def getTooltipData(self): return self.__data.tooltips def getIconsData(self): return self.__data.icons def getQuestsData(self, prefix=None, postfix=None): return self.__getProgress('quests', prefix, postfix) def getTokensData(self, prefix=None, postfix=None): return self.__getProgress('tokens', prefix, postfix) def getMarathonProgress(self, byCompletedTokensCount=True): tokens = self.getTokensData(prefix=self.prefix, postfix=self.data.completedTokenPostfix) if byCompletedTokensCount: return (len(tokens), self.data.questsInChain) tokenPrefixLen = len(self.data.tokenPrefix) res = [] for tokenNames in tokens.keys(): name = str(tokenNames[tokenPrefixLen:]) res.append(int(filter(str.isdigit, name))) currentStep = sorted(res)[-1] if res else 0 return (currentStep, self.data.questsInChain) def getState(self): return self.__state def getTooltipHeader(self): if self.data.tooltipHeaderType == PROGRESS_TOOLTIP_HEADER: return self.getFormattedDaysStatus() else: return self.getFormattedRemainingTime( ) if self.data.tooltipHeaderType == COUNTDOWN_TOOLTIP_HEADER else None def getMarathonFlagState(self, vehicle): return { 'flagHeaderIcon': self.__getHangarFlagHeaderIcon(), 'flagStateIcon': self.__getHangarFlagStateIcon(vehicle), 'flagMain': self.__getHangarFlagMain(), 'tooltip': self.__getTooltip(), 'enable': self.isAvailable(), 'visible': self.isEnabled() } def checkForWarnings(self, _): wrongBattleType = self.prbEntity.getEntityType( ) != constants.ARENA_GUI_TYPE.RANDOM return MARATHON_WARNING.WRONG_BATTLE_TYPE if wrongBattleType else '' def isVehicleObtained(self): return self.__vehInInventory def getMarathonQuests(self): return self._eventsCache.getHiddenQuests(self.__marathonFilterFunc) def getFormattedDaysStatus(self): icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON text = self.__getProgressInDays(self.__getTimeFromGroupStart()) return (icon, text) def getFormattedRemainingTime(self): firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval( ) if self.__state == MARATHON_STATE.NOT_STARTED: icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON text = self.__getTillTimeStart(firstQuestStartTimeLeft) elif self.__state == MARATHON_STATE.IN_PROGRESS: text = self.__getTillTimeEnd(firstQuestFinishTimeLeft) if firstQuestFinishTimeLeft > ONE_DAY: icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON else: icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON else: icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON text = text_styles.main(_ms(TOOLTIPS.MARATHON_STATE_COMPLETE)) return (icon, text) def getExtraDaysToBuy(self): if self.__state == MARATHON_STATE.FINISHED: _, groupFinishTimeLeft = self.__getGroupTimeInterval() if groupFinishTimeLeft < ONE_DAY: groupFinishTimeLeft += ONE_DAY fmtText = text_styles.neutral( _ms(self.data.tooltips.daysShort, value=str(int(groupFinishTimeLeft // ONE_DAY)))) return fmtText def getMarathonDiscount(self): passQuests, allQuests = self.getMarathonProgress() return int( passQuests * 100) / allQuests if passQuests and self.data.questsInChain else 0 def isShowInPostBattle(self): return self.__data.showInPostBattle def setState(self): if not self.__group: self.__isEnabled = False self.__isAvailable = False self.__state = MARATHON_STATE.UNKNOWN return self.__state if self.__suspendFlag: self.__state = MARATHON_STATE.SUSPENDED self.__isEnabled = True self.__isAvailable = False return self.__state groupStartTimeLeft, groupFinishTimeLeft = self.__getGroupTimeInterval() zeroTime = ZERO_TIME if groupStartTimeLeft > zeroTime or groupFinishTimeLeft <= zeroTime: self.__isEnabled = False self.__isAvailable = False self.__state = MARATHON_STATE.DISABLED return self.__state if groupStartTimeLeft <= zeroTime < groupFinishTimeLeft: self.__isEnabled = True self.__isAvailable = True firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval( ) if firstQuestStartTimeLeft > zeroTime: self.__state = MARATHON_STATE.NOT_STARTED elif firstQuestStartTimeLeft <= zeroTime < firstQuestFinishTimeLeft: self.__state = MARATHON_STATE.IN_PROGRESS elif firstQuestFinishTimeLeft <= zeroTime < groupFinishTimeLeft: self.__state = MARATHON_STATE.FINISHED return self.__state def updateQuestsData(self): self.__suspendFlag = False quests = self._eventsCache.getHiddenQuests(self.__marathonFilterFunc) if quests: sortedIndexList = sorted(quests) for q in sortedIndexList: if self.data.suspend in q: self.__suspendFlag = True break self.__quest = quests[sortedIndexList[0]] groups = self._eventsCache.getGroups(self.__marathonFilterFunc) if groups: sortedGroups = sorted(groups) self.__group = groups[sortedGroups[0]] else: self.__group = None tokens = self.getTokensData(prefix=self.prefix).keys() self.__vehInInventory = any( (t in tokens for t in self.data.awardTokens)) return def getClosestStatusUpdateTime(self): if self.__state == MARATHON_STATE.NOT_STARTED: timeLeft, _ = self.__getQuestTimeInterval() return timeLeft + 1 if self.__state == MARATHON_STATE.IN_PROGRESS: _, timeLeft = self.__getQuestTimeInterval() return timeLeft + 1 if self.__state == MARATHON_STATE.FINISHED: _, timeLeft = self.__getGroupTimeInterval() return timeLeft def __marathonFilterFunc(self, q): return q.getID().startswith(self.prefix) def __getProgress(self, progressType, prefix=None, postfix=None): progress = self._eventsCache.questsProgress.getCacheValue( progressType, {}) if prefix: progress = { k: v for k, v in progress.iteritems() if k.startswith(prefix) } if postfix: progress = { k: v for k, v in progress.iteritems() if k.endswith(postfix) } return progress def __getHangarFlagHeaderIcon(self): for key, imgPath in MAP_FLAG_HEADER_ICON.iteritems(): if self.__state in key: return imgPath def __getHangarFlagMain(self): return self.data.icons.mainHangarFlag def __getHangarFlagStateIcon(self, vehicle): if self.__state not in MARATHON_STATE.ENABLED_STATE: return '' if self.__vehInInventory: return self.data.icons.okIcon if self.__state == MARATHON_STATE.NOT_STARTED: return self.data.icons.timeIcon if self.__state == MARATHON_STATE.IN_PROGRESS: warning = self.checkForWarnings(vehicle) if warning: return self.data.icons.alertIcon _, firstQuestFinishTimeLeft = self.__getQuestTimeInterval() if firstQuestFinishTimeLeft > ONE_DAY: return self.data.icons.iconFlag if firstQuestFinishTimeLeft <= ONE_DAY: return self.data.icons.timeIcon return self.data.icons.saleIcon if self.__state == MARATHON_STATE.FINISHED else '' def __getTillTimeEnd(self, value): return self.__getFormattedTillTimeString(value, self.data.tooltips.stateEnd) def __getTillTimeStart(self, value): return self.__getFormattedTillTimeString(value, self.data.tooltips.stateStart, extraFmt=True) def __getProgressInDays(self, value): return self.__getTextInDays(value, self.data.tooltips.stateProgress) def __getTextInDays(self, timeValue, keyNamespace): gmtime = time.gmtime(timeValue) text = text_styles.stats( _ms(self.data.tooltips.daysShort, value=str(time.struct_time(gmtime).tm_yday))) return text_styles.main(_ms(keyNamespace, value=text)) def __getFormattedTillTimeString(self, timeValue, keyNamespace, isRoundUp=True, extraFmt=False): gmtime = time.gmtime(timeValue) if isRoundUp and gmtime.tm_sec > 0: timeValue += ONE_HOUR gmtime = time.gmtime(timeValue) if timeValue >= ONE_DAY: gmtime = time.gmtime(timeValue - ONE_DAY) text = text_styles.stats( _ms(self.data.tooltips.daysShort, value=str(time.struct_time(gmtime).tm_yday))) return text_styles.main(_ms(keyNamespace, value=text)) if extraFmt: text = text_styles.stats( _ms(self.data.tooltips.hoursShort, value=str(time.struct_time(gmtime).tm_hour))) return text_styles.main(_ms(keyNamespace, value=text)) text = _ms(self.data.tooltips.hoursShort, value=str(time.struct_time(gmtime).tm_hour)) return text_styles.tutorial(_ms(keyNamespace, value=text)) def __getTooltip(self): return TOOLTIPS_CONSTANTS.MARATHON_QUESTS_PREVIEW if self.isAvailable( ) else TOOLTIPS.MARATHON_OFF def __getTimeFromGroupStart(self): return self.__group.getTimeFromStartTillNow( ) if self.__group else ZERO_TIME def __getGroupTimeInterval(self): if self.__group: return (self.__group.getStartTimeLeft(), self.__group.getFinishTimeLeft()) zeroTime = ZERO_TIME return (zeroTime, zeroTime) def __getQuestTimeInterval(self): if self.__quest: return (self.__quest.getStartTimeLeft(), self.__quest.getFinishTimeLeft()) zeroTime = ZERO_TIME return (zeroTime, zeroTime)
class PromoController(IPromoController): PROMO_AUTO_VIEWS_TEST_VALUE = 5 browserCtrl = dependency.descriptor(IBrowserController) eventsNotification = dependency.descriptor(IEventsNotificationsController) def __init__(self): super(PromoController, self).__init__() self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self._isPromoShown = False return def fini(self): self._stop() self.__urlMacros.clear() self.__urlMacros = None super(PromoController, self).fini() return def onLobbyInited(self, event): if not isPlayerAccount(): return self._updatePromo(self._getPromoEventNotifications()) self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted self._processPromo(self.eventsNotification.getEventsNotifications()) def onAvatarBecomePlayer(self): self._stop() def onDisconnected(self): self._stop() self._isPromoShown = False @process def showCurrentVersionPatchPromo(self, isAsync=False): self.__currentVersionBrowserID = yield self.__showPromoBrowser( self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE), browserID=self.__currentVersionBrowserID, isAsync=isAsync, showWaiting=not isAsync) @process def showVersionsPatchPromo(self): promoUrl = yield self.__urlMacros.parse(GUI_SETTINGS.promoscreens) promoTitle = i18n.makeString(MENU.PROMO_PATCH_TITLE) self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, promoTitle, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) @process def showPromo(self, url, title): promoUrl = yield self.__urlMacros.parse(url) self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, title, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) def isPatchPromoAvailable(self): return self.__currentVersionPromoUrl is not None and GUI_SETTINGS.isPatchPromoEnabled def isPatchChanged(self): mainVersion = getClientMainVersion() return mainVersion is not None and AccountSettings.getSettings( LAST_PROMO_PATCH_VERSION) != mainVersion def _stop(self): self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification return @process def _processPromo(self, promo): yield lambda callback: callback(True) if self.isPatchPromoAvailable() and self.isPatchChanged( ) and self.isPromoAutoViewsEnabled() and not self._isPromoShown: LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl) AccountSettings.setSettings(LAST_PROMO_PATCH_VERSION, getClientMainVersion()) self.__currentVersionBrowserShown = True self._isPromoShown = True self.showCurrentVersionPatchPromo(isAsync=True) return actionsPromo = [ item for item in promo if item.eventType.startswith(gc_constants.PROMO.TEMPLATE.ACTION) ] for actionPromo in actionsPromo: promoUrl = yield self.__urlMacros.parse(actionPromo.data) promoTitle = actionPromo.text if promoUrl not in self.__promoShown and not self._isPromoShown and promoUrl != self.__currentVersionPromoUrl: LOG_DEBUG('Showing action promo:', promoUrl) self.__promoShown.add(promoUrl) self.__savePromoShown() self._isPromoShown = True yield self.__showPromoBrowser(promoUrl, promoTitle) return @process def _updatePromo(self, promosData): yield lambda callback: callback(True) for item in filter( lambda item: item.eventType == gc_constants.PROMO.TEMPLATE. ACTION, promosData): promoUrl = yield self.__urlMacros.parse(item.data) self.__availablePromo.add(promoUrl) if self.__currentVersionPromoUrl is None: self.__currentVersionPromoUrl = yield self.__urlMacros.parse( GUI_SETTINGS.currentVersionPromo) promoShownSource = AccountSettings.getFilter(PROMO) self.__promoShown = { url for url in promoShownSource if url in self.__availablePromo } self.__savePromoShown() return def _getPromoEventNotifications(self): def filterFunc(item): return item.eventType == gc_constants.PROMO.TEMPLATE.ACTION return self.eventsNotification.getEventsNotifications(filterFunc) def __savePromoShown(self): AccountSettings.setFilter(PROMO, self.__promoShown) def __onEventNotification(self, added, removed): self._updatePromo(self._getPromoEventNotifications()) self._processPromo(added) def __onBrowserDeleted(self, browserID): if self.__currentVersionBrowserID == browserID: self.__currentVersionBrowserID = None if self.__currentVersionBrowserShown: self.__currentVersionBrowserShown = False g_eventBus.handleEvent(events.BubbleTooltipEvent( events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY) return @async @process def __showPromoBrowser(self, promoUrl, promoTitle, browserID=None, isAsync=True, showWaiting=False, callback=None): browserID = yield self.browserCtrl.load( promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, isDefault=False, showCloseBtn=True, showWaiting=showWaiting) callback(browserID) @classmethod def isPromoAutoViewsEnabled(cls): return getAccountDatabaseID( ) % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and g_lobbyContext.getServerSettings( ).isPromoAutoViewsEnabled()
class MarathonEventController(IMarathonEventController, Notifiable): _eventsCache = dependency.descriptor(IEventsCache) _bootcamp = dependency.descriptor(IBootcampController) def __init__(self): super(MarathonEventController, self).__init__() self.__isEnabled = False self.__isAvailable = False self.__vehInInventory = False self.__state = '' self.__suspendFlag = False self.__marathonQuest = None self.__marathonGroup = None self.__urlMacros = URLMarcos() self.__baseUrl = GUI_SETTINGS.lookup('marathonUrl') self.__eventManager = Event.EventManager() self.onFlagUpdateNotify = Event.Event(self.__eventManager) return def fini(self): self.__stop() super(MarathonEventController, self).fini() def onLobbyStarted(self, ctx): super(MarathonEventController, self).onLobbyStarted(ctx) self._eventsCache.onSyncCompleted += self.__onSyncCompleted self._eventsCache.onProgressUpdated += self.__onSyncCompleted self.__onSyncCompleted() def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @prbEntityProperty def prbEntity(self): return None @async @process def getURL(self, callback): if self.__baseUrl is None: LOG_ERROR( 'Requesting URL for marathon when base URL is not specified') yield lambda clb: clb(False) else: url = yield self.__urlMacros.parse(self.__baseUrl) callback(url) return def isEnabled(self): return self.__isEnabled and not self._bootcamp.isInBootcamp() def isAvailable(self): return self.__isAvailable def getQuestsData(self, prefix=None, postfix=None): return self.__getProgress('quests', prefix, postfix) def getTokensData(self, prefix=None, postfix=None): return self.__getProgress('tokens', prefix, postfix) def getMarathonProgress(self): tokens = self.getTokensData(prefix=MARATHON_PREFIX, postfix=MARATHON_COMPLETED_TOKEN_POSTFIX) tokenPrefixLen = len('event_marathon:IM18') res = [] for tokenNames in tokens.keys(): name = str(tokenNames[tokenPrefixLen:]) res.append(int(filter(str.isdigit, name))) currentStep = sorted(res)[-1] if res else 0 return (currentStep, MARATHON_QUESTS_IN_CHAIN) def getState(self): return self.__state def getMarathonFlagState(self, vehicle): return { 'flagHeaderIcon': self.__getHangarFlagHeaderIcon(), 'flagStateIcon': self.__getHangarFlagStateIcon(vehicle), 'tooltip': self.__getTooltip(), 'enable': self.isAvailable(), 'visible': self.isEnabled() } def checkForWarnings(self, _): wrongBattleType = self.prbEntity.getEntityType( ) != constants.ARENA_GUI_TYPE.RANDOM return MARATHON_WARNING.WRONG_BATTLE_TYPE if wrongBattleType else '' def isVehicleObtained(self): return self.__vehInInventory def getMarathonQuests(self): return self._eventsCache.getHiddenQuests(marathonFilterFunc) def getFormattedRemainingTime(self): firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval( ) if self.__state == MARATHON_STATE.NOT_STARTED: icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON text = self.__getTillTimeStart(firstQuestStartTimeLeft) elif self.__state == MARATHON_STATE.IN_PROGRESS: text = self.__getTillTimeEnd(firstQuestFinishTimeLeft) if firstQuestFinishTimeLeft > ONE_DAY: icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON else: icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON else: icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON text = text_styles.main(_ms(TOOLTIPS.MARATHON_STATE_COMPLETE)) return (icon, text) def getExtraDaysToBuy(self): if self.__state == MARATHON_STATE.FINISHED: _, groupFinishTimeLeft = self.__getGroupTimeInterval() if groupFinishTimeLeft < ONE_DAY: groupFinishTimeLeft += ONE_DAY fmtText = text_styles.neutral( _ms(TOOLTIPS.TEMPLATE_DAYS_SHORT, value=str(int(groupFinishTimeLeft // ONE_DAY)))) return fmtText def getMarathonDiscount(self): passQuests, allQuests = self.getMarathonProgress() return int( passQuests * 100) / allQuests if passQuests and MARATHON_QUESTS_IN_CHAIN else 0 def __onSyncCompleted(self, *args): self.__checkEvents() self.__reloadNotification() def __checkEvents(self): self.__updateQuestsData() self.__setState() def __setState(self): if not self.__marathonGroup: self.__isEnabled = False self.__isAvailable = False self.__state = MARATHON_STATE.UNKNOWN return self.__state if self.__suspendFlag: self.__state = MARATHON_STATE.SUSPENDED self.__isEnabled = True self.__isAvailable = False return self.__state groupStartTimeLeft, groupFinishTimeLeft = self.__getGroupTimeInterval() if groupStartTimeLeft > ZERO_TIME or groupFinishTimeLeft <= ZERO_TIME: self.__isEnabled = False self.__isAvailable = False self.__state = MARATHON_STATE.DISABLED return self.__state if groupStartTimeLeft <= ZERO_TIME < groupFinishTimeLeft: self.__isEnabled = True self.__isAvailable = True firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval( ) if firstQuestStartTimeLeft > ZERO_TIME: self.__state = MARATHON_STATE.NOT_STARTED elif firstQuestStartTimeLeft <= ZERO_TIME < firstQuestFinishTimeLeft: self.__state = MARATHON_STATE.IN_PROGRESS elif firstQuestFinishTimeLeft <= ZERO_TIME < groupFinishTimeLeft: self.__state = MARATHON_STATE.FINISHED return self.__state def __updateQuestsData(self): self.__suspendFlag = False quests = self._eventsCache.getHiddenQuests(marathonFilterFunc) if quests: sortedIndexList = sorted(quests) for q in sortedIndexList: if MARATHON_SUSPEND in q: self.__suspendFlag = True break self.__marathonQuest = quests[sortedIndexList[0]] groups = self._eventsCache.getGroups(marathonFilterFunc) if groups: sortedGroups = sorted(groups) self.__marathonGroup = groups[sortedGroups[0]] tokens = self.getTokensData(prefix=MARATHON_PREFIX).keys() self.__vehInInventory = any( (t in tokens for t in MARATHON_AWARD_TOKENS)) def __getProgress(self, progressType, prefix=None, postfix=None): progress = self._eventsCache.questsProgress.getCacheValue( progressType, {}) if prefix: progress = { k: v for k, v in progress.iteritems() if k.startswith(prefix) } if postfix: progress = { k: v for k, v in progress.iteritems() if k.endswith(postfix) } return progress def __getHangarFlagHeaderIcon(self): for key, imgPath in MAP_FLAG_HEADER_ICON.iteritems(): if self.__state in key: return imgPath def __getHangarFlagStateIcon(self, vehicle): if self.__state not in MARATHON_STATE.ENABLED_STATE: return '' if self.__vehInInventory: return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_OK_ICON if self.__state == MARATHON_STATE.NOT_STARTED: return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_TIME_ICON if self.__state == MARATHON_STATE.IN_PROGRESS: warning = self.checkForWarnings(vehicle) if warning: return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_ALERT_ICON _, firstQuestFinishTimeLeft = self.__getQuestTimeInterval() if firstQuestFinishTimeLeft > ONE_DAY: return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_ICON_FLAG if firstQuestFinishTimeLeft <= ONE_DAY: return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_TIME_ICON return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_SALE_ICON if self.__state == MARATHON_STATE.FINISHED else None def __getTillTimeEnd(self, value): return self.__getFormattedTillTimeString(value, TOOLTIPS.MARATHON_STATE_END) def __getTillTimeStart(self, value): return self.__getFormattedTillTimeString(value, TOOLTIPS.MARATHON_STATE_START, extraFmt=True) def __getFormattedTillTimeString(self, timeValue, keyNamespace, isRoundUp=True, extraFmt=False): gmtime = time.gmtime(timeValue) if isRoundUp and gmtime.tm_sec > 0: timeValue += ONE_HOUR gmtime = time.gmtime(timeValue) if timeValue >= ONE_DAY: gmtime = time.gmtime(timeValue - ONE_DAY) text = text_styles.stats( _ms(TOOLTIPS.TEMPLATE_DAYS_SHORT, value=str(time.struct_time(gmtime).tm_yday))) return text_styles.main(_ms(keyNamespace, value=text)) if extraFmt: text = text_styles.stats( _ms(TOOLTIPS.TEMPLATE_HOURS_SHORT, value=str(time.struct_time(gmtime).tm_hour))) return text_styles.main(_ms(keyNamespace, value=text)) text = _ms(TOOLTIPS.TEMPLATE_HOURS_SHORT, value=str(time.struct_time(gmtime).tm_hour)) return text_styles.tutorial(_ms(keyNamespace, value=text)) def __getTooltip(self): return TOOLTIPS_CONSTANTS.MARATHON_QUESTS_PREVIEW if self.isAvailable( ) else TOOLTIPS.MARATHON_OFF def __getGroupTimeInterval(self): return (self.__marathonGroup.getStartTimeLeft(), self.__marathonGroup.getFinishTimeLeft() ) if self.__marathonGroup else (ZERO_TIME, ZERO_TIME) def __getQuestTimeInterval(self): return (self.__marathonQuest.getStartTimeLeft(), self.__marathonQuest.getFinishTimeLeft() ) if self.__marathonQuest else (ZERO_TIME, ZERO_TIME) def __stop(self): self.clearNotification() self._eventsCache.onSyncCompleted -= self.__onSyncCompleted self._eventsCache.onProgressUpdated -= self.__onSyncCompleted def __getClosestStatusUpdateTime(self): if self.__state == MARATHON_STATE.NOT_STARTED: timeLeft, _ = self.__getQuestTimeInterval() return timeLeft + 1 if self.__state == MARATHON_STATE.IN_PROGRESS: _, timeLeft = self.__getQuestTimeInterval() return timeLeft + 1 if self.__state == MARATHON_STATE.FINISHED: _, timeLeft = self.__getGroupTimeInterval() return timeLeft def __updateFlagState(self): self.__checkEvents() self.onFlagUpdateNotify() def __reloadNotification(self): self.clearNotification() timePeriod = self.__getClosestStatusUpdateTime() if timePeriod: self.addNotificator( PeriodicNotifier(self.__getClosestStatusUpdateTime, self.__updateFlagState)) self.startNotification()
class ExternalLinksHandler(Controller): def __init__(self, proxy): super(ExternalLinksHandler, self).__init__(proxy) self.__urlMarcos = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(ExternalLinksHandler, self).fini() return def open(self, url): if not url: LOG_ERROR('URL is empty', url) return try: BigWorld.wg_openWebBrowser(url) except Exception: LOG_ERROR('There is error while opening web browser at page:', url) LOG_CURRENT_EXCEPTION() @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) def _handleSpecifiedURL(self, event): self.open(event.url) @process def __openParsedUrl(self, urlName): parsedUrl = yield self.getURL(urlName) self.open(parsedUrl) def _handleOpenRegistrationURL(self, _): self.__openParsedUrl('registrationURL') def _handleOpenRecoveryPasswordURL(self, _): self.__openParsedUrl('recoveryPswdURL') def _handleOpenPaymentURL(self, _): self.__openParsedUrl('paymentURL') def _handleSecuritySettingsURL(self, _): self.__openParsedUrl('securitySettingsURL') def _handleSupportURL(self, _): self.__openParsedUrl('supportURL') def _handleMigrationURL(self): self.__openParsedUrl('migrationURL') def _handleFortDescription(self, _): self.__openParsedUrl('fortDescription') def _handleClanSearch(self, _): self.__openParsedUrl('clanSearch') def _handleClanCreate(self, _): self.__openParsedUrl('clanCreate') def _handleClubSettings(self, _): self.__openParsedUrl('clubSettings') def _handleInvitesManagementURL(self, _): self.__openParsedUrl('invitesManagementURL') def _handleGmSummaryURL(self, _): self.__openParsedUrl('globalMapSummary') def _handleGmPromoSummaryURL(self, _): self.__openParsedUrl('globalMapPromoSummary') def _handleGmCapURL(self, _): self.__openParsedUrl('globalMapCap') def _handleGmPromoURL(self, _): self.__openParsedUrl('globalMapPromo')
class ExternalLinksHandler(IExternalLinksController): def __init__(self): super(ExternalLinksHandler, self).__init__() self.__urlMarcos = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(ExternalLinksHandler, self).fini() return def open(self, url): if not url: LOG_ERROR('URL is empty', url) return try: BigWorld.wg_openWebBrowser(url) except Exception: LOG_ERROR('There is error while opening web browser at page:', url) LOG_CURRENT_EXCEPTION() @async @process def getURL(self, name, params=None, callback=lambda *args: None): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings), params) else: url = yield lambda callback: callback('') callback(url) def _handleSpecifiedURL(self, event): self.open(event.url) @process def __openParsedUrl(self, urlName, params=None): parsedUrl = yield self.getURL(urlName, params) self.open(parsedUrl) def _handleOpenRegistrationURL(self, _): self.__openParsedUrl('registrationURL') def _handleOpenRecoveryPasswordURL(self, _): self.__openParsedUrl('recoveryPswdURL') def _handleOpenPaymentURL(self, _): self.__openParsedUrl('paymentURL') def _handleSecuritySettingsURL(self, _): self.__openParsedUrl('securitySettingsURL') def _handleSupportURL(self, _): self.__openParsedUrl('supportURL') def _handleMigrationURL(self): self.__openParsedUrl('migrationURL') def _handleFortDescription(self, _): self.__openParsedUrl('fortDescription') def _handleClanSearch(self, _): self.__openParsedUrl('clanSearch') def _handleClanCreate(self, _): self.__openParsedUrl('clanCreate') def _handleInvitesManagementURL(self, _): self.__openParsedUrl('invitesManagementURL') def _handleGmSummaryURL(self, _): self.__openParsedUrl('globalMapSummary') def _handleGmPromoSummaryURL(self, _): self.__openParsedUrl('globalMapPromoSummary') def _handleGmCapURL(self, _): self.__openParsedUrl('globalMapCap') def _handleGmPromoURL(self, _): self.__openParsedUrl('globalMapPromo') def _handleOpenPremShopURL(self, _): self.__openParsedUrl('premShopURL') def _handleTokenShopURL(self, event): self.__openParsedUrl('tokenShopURL', event.params)
class EncyclopediaController(Controller): """ Manages queue of encyclopedia recommendations and activation state of encyclopedia feature """ def __init__(self, proxy): super(EncyclopediaController, self).__init__(proxy) self.__activated = False self.__recommendations = [] self.__eventManager = Event.EventManager() self.__urlMacros = URLMarcos() self.__isLobbyStarted = False self.__hasNewRecommendations = False if GUI_SETTINGS.lookup('encyclopedia'): self.__baseUrl = GUI_SETTINGS.encyclopedia['url'] self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled'] else: self.__baseUrl = None self.__isSuitableLanguage = False self.onNewRecommendationReceived = Event.Event(self.__eventManager) self.onStateChanged = Event.Event(self.__eventManager) self.__isStateSynced = False return def onAccountBecomePlayer(self): g_settingsCache.onSyncCompleted += self.__updateRecommendations def onConnected(self): if GUI_SETTINGS.lookup('encyclopedia'): self.__baseUrl = GUI_SETTINGS.encyclopedia['url'] self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled'] def onLobbyStarted(self, _): self.__isLobbyStarted = True self.__updateRecommendations() self.__updateActivationState() def onAvatarBecomePlayer(self): self.__isLobbyStarted = False g_settingsCache.onSyncCompleted -= self.__updateRecommendations def onDisconnected(self): self.__isStateSynced = False def fini(self): self.__eventManager.clear() super(EncyclopediaController, self).fini() def isActivated(self): return self.__activated def hasNewRecommendations(self): return self.__hasNewRecommendations def getRecommendations(self): return self.__recommendations def addEncyclopediaRecommendation(self, recId): if not self.__isLobbyStarted: return recId = int(recId) if 0 <= recId > _MAX_RECOMMENDATION_ID: LOG_ERROR('Recommendation ID is out of range', recId) return if self.__recommendations and self.__recommendations[0] == recId: return if recId in self.__recommendations: self.__recommendations.remove(recId) self.__recommendations.insert(0, recId) self.__recommendations = self.__recommendations[:_RECOMMENDATIONS_COUNT] _setEncyclopediaRecommendationsSections(self.__recommendations) g_settingsCore.serverSettings.setHasNewEncyclopediaRecommendations() self.onNewRecommendationReceived() if self.isActivated(): pushI18nMessage(SYSTEM_MESSAGES.PRMP_NOTIFICATION_NEWENCYCLOPEDIARECOMMENDATION, priority=NotificationPriorityLevel.MEDIUM) def moveEncyclopediaRecommendationToEnd(self, recId): recId = int(recId) if recId in self.__recommendations: self.__recommendations.remove(recId) self.__recommendations.append(recId) _setEncyclopediaRecommendationsSections(self.__recommendations) def resetHasNew(self): self.__hasNewRecommendations = False g_settingsCore.serverSettings.setHasNewEncyclopediaRecommendations(False) @async @process def buildUrl(self, callback): if self.__baseUrl is None: LOG_ERROR('Requesting URL for encyclopedia when base URL is not specified') yield lambda clb: clb(False) else: queryParams = {'id': self.getRecommendations()} url = yield self.__urlMacros.parse(self.__baseUrl) callback(addParamsToUrlQuery(url, queryParams)) return def __updateRecommendations(self): self.__recommendations = _getEncyclopediaRecommendations() self.__hasNewRecommendations = g_settingsCore.serverSettings.getHasNewEncyclopediaRecommendations() def __updateActivationState(self, *_): if self.__baseUrl is None or not self.__isSuitableLanguage or self.__isStateSynced: return False else: tokensCount = g_eventsCache.questsProgress.getTokenCount(_ACTIVATION_TOKEN) newState = g_lobbyContext.getServerSettings().isEncyclopediaEnabled(tokensCount) self.__isStateSynced = True if newState != self.__activated: self.__activated = newState self.onStateChanged() return
class PersonalMissionFirstEntryView(LobbySubView, PersonalMissionFirstEntryViewMeta): browserCtrl = dependency.descriptor(IBrowserController) _COMMON_SOUND_SPACE = PERSONAL_MISSIONS_SOUND_SPACE __settingsCore = dependency.descriptor(ISettingsCore) __CARDS = (3, 3, 4, 4) def __init__(self, ctx): super(PersonalMissionFirstEntryView, self).__init__(ctx) self.__currentVersionBrowserID = None self.__urlMacros = URLMarcos() self.__settings = GUI_SETTINGS.personalMissions.get('welcomeVideo', {}) self.__cardsLen = len(self.__CARDS) return def playVideo(self): if self.__settings.get('isEnabled', False): self.__showVideo() def backBtnClicked(self): self.__currentVersionBrowserID = None self.fireEvent(events.LoadViewEvent( VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS), scope=EVENT_BUS_SCOPE.LOBBY) return def onViewClose(self, isAcceptBtnClick=False): if isAcceptBtnClick: self.__settingsCore.serverSettings.saveInUIStorage( {PM_TUTOR_FIELDS.GREETING_SCREEN_SHOWN: True}) self.fireEvent(events.LoadViewEvent( VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS), scope=EVENT_BUS_SCOPE.LOBBY) else: self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_HANGAR), scope=EVENT_BUS_SCOPE.LOBBY) def onCardClick(self, cardIndex): self.__updateDetailedData(cardIndex) def onNextCardClick(self, cardIndex): self.__updateDetailedData(cardIndex + 1) def onPrevCardClick(self, cardIndex): self.__updateDetailedData(cardIndex - 1) def _populate(self): super(PersonalMissionFirstEntryView, self)._populate() infoBlocks = [ self.__makeTileData(cardIndex) for cardIndex in xrange(0, self.__cardsLen) ] firstEntry = not self.__settingsCore.serverSettings.getUIStorage().get( PM_TUTOR_FIELDS.GREETING_SCREEN_SHOWN) self.as_setInitDataS({ 'titleLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_TITLE, 'bigBtnLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ACKNOWLEDGEBTN, 'playVideoBtnLabel': text_styles.concatStylesToSingleLine( icons.makeImageTag( RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_PLAYICON, width=14, height=15, vSpace=-2), i18n.makeString(PERSONAL_MISSIONS. PERSONALMISSIONFIRSTENTRYVIEW_VIDEOBTNLABEL)), 'playVideoBtnVisible': self.__settings.get('isEnabled', False), 'bgSource': RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_INFOSCREENBG, 'infoBlocks': infoBlocks, 'backBtnLabel': PERSONAL_MISSIONS.HEADER_BACKBTN_LABEL, 'isFirstEntry': firstEntry }) self.soundManager.setRTPC(SOUNDS.RTCP_OVERLAY, SOUNDS.MAX_MISSIONS_ZOOM) def _dispose(self): self.soundManager.setRTPC(SOUNDS.RTCP_OVERLAY, SOUNDS.MIN_MISSIONS_ZOOM) super(PersonalMissionFirstEntryView, self)._dispose() def __updateDetailedData(self, cardIndex): cardIndex = self.__normalizeSlotIndex(cardIndex) blocksLen = self.__CARDS[cardIndex] blocks = [] for blockIndex in xrange(0, blocksLen): blocks.append({ 'title': PERSONAL_MISSIONS.getBlockTitle(cardIndex, blockIndex), 'description': PERSONAL_MISSIONS.getBlockDescription(cardIndex, blockIndex), 'image': RES_ICONS.getBlockImageByStep(cardIndex, blockIndex) }) data = { 'index': cardIndex, 'icon': RES_ICONS.getInfoIcon(cardIndex), 'title': PERSONAL_MISSIONS.getCardHeader(cardIndex), 'description': PERSONAL_MISSIONS.getCardInnerDescription(cardIndex), 'blocks': blocks, 'notificationIcon': RES_ICONS.MAPS_ICONS_LIBRARY_WARNINGICON_1, 'notificationLabel': i18n.makeString(PERSONAL_MISSIONS.getBlockWarning(cardIndex)) } self.as_setDetailedCardDataS(data) @process def __showVideo(self): url = yield self.__urlMacros.parse(self.__settings.get('url')) webBrowser = self.__getCurrentBrowser() if not webBrowser or url != webBrowser.url: title = i18n.makeString( PERSONAL_MISSIONS.PERSONALMISSIONS_VIDEO_TITLE) self.__currentVersionBrowserID = yield self.browserCtrl.load( url, title, showActionBtn=False, browserID=self.__currentVersionBrowserID, browserSize=gc_constants.BROWSER.VIDEO_SIZE, isDefault=False, showCloseBtn=True, handlers=webApiCollection(HangarSoundWebApi)) @staticmethod def __makeTileData(cardIndex): return { 'index': cardIndex, 'iconSource': RES_ICONS.getInfoIcon(cardIndex), 'titleLabel': PERSONAL_MISSIONS.getCardHeader(cardIndex), 'descriptionLabel': PERSONAL_MISSIONS.getCardDescription(cardIndex) } def __getCurrentBrowser(self): return self.browserCtrl.getBrowser(self.__currentVersionBrowserID) def __normalizeSlotIndex(self, slotIndex): if slotIndex >= self.__cardsLen: return 0 return self.__cardsLen - 1 if slotIndex < 0 else slotIndex
class RssNewsFeed(RssNewsFeedMeta): UPDATE_INTERVAL = 60 DESCRIPTION_MAX_LENGTH = 250 DESCRIPTION_TAIL = '...' DESCRIPTION_CUT_LENGTH = DESCRIPTION_MAX_LENGTH - len(DESCRIPTION_TAIL) SHOW_NEWS_COUNT = 3 def __init__(self): super(RssNewsFeed, self).__init__() self.__requestCbID = None self.__feed = [] self.__urlMacros = URLMarcos() return def getFeed(self): return self.__feed def openBrowser(self, linkToOpen): if linkToOpen: openBrowser = game_control.g_instance.links.open if GUI_SETTINGS.loginRssFeed.internalBrowser: browser = game_control.g_instance.browser if browser is not None: openBrowser = browser.load else: LOG_ERROR('Attempting to open internal browser, but browseris not exist. External browser will be opened', str(linkToOpen)) LOG_DEBUG('Open browser', linkToOpen) openBrowser(linkToOpen) return def _populate(self): super(RssNewsFeed, self)._populate() self.__updateCallback() def _dispose(self): self.__urlMacros.clear() self.__urlMacros = None self.__feed = [] self.__clearCallback() super(RssNewsFeed, self)._dispose() return @process def __requestFeed(self): yield lambda callback: callback(True) if GUI_SETTINGS.loginRssFeed.show: requestUrl = yield self.__getRssUrl() from helpers.RSSDownloader import g_downloader as g_rss if g_rss is not None: g_rss.download(self.__onRssFeedReceived, url=requestUrl) LOG_DEBUG('Requesting login RSS news', requestUrl) return def __onRssFeedReceived(self, data): if self.isDisposed(): return else: self.__feed = [] for entry in reversed(data.get('entries', [])): data = self.__prepareData(entry) if data is not None: self.__feed.append(data) LOG_DEBUG('RSS feed received, entries count', len(self.__feed)) self.as_updateFeedS(self.__feed[:self.SHOW_NEWS_COUNT]) return def __clearCallback(self): if self.__requestCbID is not None: BigWorld.cancelCallback(self.__requestCbID) self.__requestCbID = None return def __updateCallback(self): self.__requestFeed() self.__clearCallback() self.__requestCbID = BigWorld.callback(self.UPDATE_INTERVAL, self.__updateCallback) @async @process def __getRssUrl(self, callback): if constants.IS_CHINA: callback('http://wot.kongzhong.com/erji/login_ticker.xml') url = yield self.__urlMacros.parse(str(GUI_SETTINGS.loginRssFeed.url)) callback(url) def __prepareData(self, entryData): description = entryData.get('description') if description is not None: try: section = ResMgr.DataSection() section.createSectionFromString(encodeUtf8(description)) _, section = findFirst(lambda (name, _): name == 'div', section.items()) description, _ = unicode_from_utf8(section.asString) if len(description) > self.DESCRIPTION_MAX_LENGTH: description = description[:self.DESCRIPTION_CUT_LENGTH] + self.DESCRIPTION_TAIL except Exception: LOG_ERROR('Invalid RSS entry description', entryData, description) LOG_CURRENT_EXCEPTION() return return {'id': entryData.get('id', str(uuid.uuid4())), 'link': entryData.get('link'), 'description': encodeUtf8(description)}
def __init__(self): super(RssNewsFeed, self).__init__() self.__requestCbID = None self.__feed = [] self.__urlMacros = URLMarcos() return
class EncyclopediaController(IEncyclopediaController): eventsCache = dependency.descriptor(IEventsCache) settingsCache = dependency.descriptor(ISettingsCache) settingsCore = dependency.descriptor(ISettingsCore) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(EncyclopediaController, self).__init__() self.__activated = False self.__recommendations = [] self.__eventManager = Event.EventManager() self.__urlMacros = URLMarcos() self.__isLobbyStarted = False self.__hasNewRecommendations = False if GUI_SETTINGS.lookup('encyclopedia'): self.__baseUrl = GUI_SETTINGS.encyclopedia['url'] self.__isSuitableLanguage = getClientLanguage( ) in GUI_SETTINGS.encyclopedia.get('languages', ()) else: self.__baseUrl = None self.__isSuitableLanguage = False self.onNewRecommendationReceived = Event.Event(self.__eventManager) self.onStateChanged = Event.Event(self.__eventManager) self.__isStateSynced = False return def onAccountBecomePlayer(self): self.settingsCache.onSyncCompleted += self.__updateRecommendations def onConnected(self): if GUI_SETTINGS.lookup('encyclopedia'): self.__baseUrl = GUI_SETTINGS.encyclopedia['url'] self.__isSuitableLanguage = getClientLanguage( ) in GUI_SETTINGS.encyclopedia.get('languages', ()) def onLobbyStarted(self, _): self.__isLobbyStarted = True self.__updateRecommendations() self.__updateActivationState() def onAvatarBecomePlayer(self): self.__isLobbyStarted = False self.settingsCache.onSyncCompleted -= self.__updateRecommendations def onDisconnected(self): self.__isStateSynced = False def fini(self): self.__eventManager.clear() super(EncyclopediaController, self).fini() def isActivated(self): return self.__activated def hasNewRecommendations(self): return self.__hasNewRecommendations def getRecommendations(self): return self.__recommendations def addEncyclopediaRecommendation(self, recId): if not self.__isLobbyStarted: return recId = int(recId) if 0 <= recId > _MAX_RECOMMENDATION_ID: LOG_ERROR('Recommendation ID is out of range', recId) return if self.__recommendations and self.__recommendations[0] == recId: return if recId in self.__recommendations: self.__recommendations.remove(recId) self.__recommendations.insert(0, recId) self.__recommendations = self.__recommendations[: _RECOMMENDATIONS_COUNT] _setEncyclopediaRecommendationsSections(self.__recommendations, self.settingsCore) self.settingsCore.serverSettings.setHasNewEncyclopediaRecommendations() self.onNewRecommendationReceived() if self.isActivated(): pushI18nMessage(SYSTEM_MESSAGES. PRMP_NOTIFICATION_NEWENCYCLOPEDIARECOMMENDATION, priority=NotificationPriorityLevel.MEDIUM) def moveEncyclopediaRecommendationToEnd(self, recId): recId = int(recId) if recId in self.__recommendations: self.__recommendations.remove(recId) self.__recommendations.append(recId) _setEncyclopediaRecommendationsSections(self.__recommendations, self.settingsCore) def resetHasNew(self): self.__hasNewRecommendations = False self.settingsCore.serverSettings.setHasNewEncyclopediaRecommendations( False) @async @process def buildUrl(self, callback): if self.__baseUrl is None: LOG_ERROR( 'Requesting URL for encyclopedia when base URL is not specified' ) yield lambda clb: clb(False) else: queryParams = {'id': self.getRecommendations()} url = yield self.__urlMacros.parse(self.__baseUrl) callback(addParamsToUrlQuery(url, queryParams)) return def __updateRecommendations(self): self.__recommendations = _getEncyclopediaRecommendations( self.settingsCore) self.__hasNewRecommendations = self.settingsCore.serverSettings.getHasNewEncyclopediaRecommendations( ) def __updateActivationState(self, *_): if self.__baseUrl is None or not self.__isSuitableLanguage or self.__isStateSynced: return False else: tokensCount = self.eventsCache.questsProgress.getTokenCount( _ACTIVATION_TOKEN) newState = self.lobbyContext.getServerSettings( ).isEncyclopediaEnabled(tokensCount) self.__isStateSynced = True if newState != self.__activated: self.__activated = newState self.onStateChanged() return
class CalendarController(ICalendarController): """Advent calendar controller. This controller shows the in-game browser pointing to the advent calendar web-app in following scenarios: * The player clicks on related item in the Hangar. * The player clicks on related Action in the Shop. * On lobby startup once in a day, if allowed by server. """ browserCtrl = dependency.descriptor(IBrowserController) eventsCache = dependency.descriptor(IEventsCache) def __init__(self): super(CalendarController, self).__init__() self.__browserID = None self.__browserLoaded = False self.__showOnSplash = False self.__urlMacros = URLMarcos() return def init(self): self.eventsCache.onSyncCompleted += self.__onSyncCompleted self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted g_eventBus.addListener(events.BrowserEvent.BROWSER_CREATED, self.__onBrowserCreated) def fini(self): self.__urlMacros.clear() self.__urlMacros = None self.hideCalendar() g_eventBus.removeListener(events.BrowserEvent.BROWSER_CREATED, self.__onBrowserCreated) self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted self.eventsCache.onSyncCompleted -= self.__onSyncCompleted super(CalendarController, self).fini() return def onLobbyStarted(self, event): if self.__showOnSplash: lastShowTstamp = self.__getShowTimestamp() now = time_utils.getServerUTCTime() if lastShowTstamp is not None: today = time_utils.getDayTimeBoundsForUTC(now)[0] offset = _START_OF_DAY_OFFSET.get(constants.CURRENT_REALM, timedelta(0)).total_seconds() dayStart = today + offset mustShow = lastShowTstamp < dayStart <= now or lastShowTstamp > now else: mustShow = True if mustShow: self.showCalendar(CalendarInvokeOrigin.SPLASH) self.__setShowTimestamp(now) return def onAvatarBecomePlayer(self): self.hideCalendar() def onDisconnected(self): self.hideCalendar() def showCalendar(self, invokedFrom): """Show the advent calendar in browser window.""" if self.__browserID is not None: if self.__browserLoaded: _logger.debug('Calendar already opened, bringing window to focus (browserID=%d)' % self.__browserID) g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.ADVENT_CALENDAR, name=_genWindowName(self.__browserID)), scope=EVENT_BUS_SCOPE.LOBBY) return else: try: while self.__browserID is None: browserID = next(_browserIDGen) if self.browserCtrl.getBrowser(browserID) is None: self.__browserID = browserID except StopIteration: _logger.error('Could not allocate a browser ID for calendar') return self.__openBrowser(self.__browserID, _BROWSER_SIZE, invokedFrom) _logger.debug('Calendar opening scheduled (browserID=%d)' % self.__browserID) return def hideCalendar(self): if self.__browserID is None: return else: self.browserCtrl.delBrowser(self.__browserID) return def __onSyncCompleted(self, *_): def calendarEnabledActionFilter(act): return any((isinstance(mod, CalendarSplashModifier) for mod in act.getModifiers())) self.__showOnSplash = len(self.eventsCache.getActions(calendarEnabledActionFilter)) > 0 def __onBrowserDeleted(self, browserID): if browserID == self.__browserID: _logger.debug('Calendar WebBrowser instance destroyed (browserID=%d)' % browserID) self.__browserID = None self.__browserLoaded = False return def __onBrowserCreated(self, event): browserID = event.ctx.get('browserID') if browserID == self.__browserID: _logger.debug('Calendar WebBrowser instance created (browserID=%d)' % browserID) browser = self.browserCtrl.getBrowser(browserID) browser.useSpecialKeys = False self.__browserLoaded = True def __getShowTimestamp(self): tstampStr = AccountSettings.getSettings(LAST_CALENDAR_SHOW_TIMESTAMP) if tstampStr: try: return float(tstampStr) except (TypeError, ValueError): _logger.warning('Invalid calendar show timestamp') return None def __setShowTimestamp(self, tstamp): AccountSettings.setSettings(LAST_CALENDAR_SHOW_TIMESTAMP, str(tstamp)) @process def __openBrowser(self, browserID, browserSize, invokedFrom): """Shows the event calendar browser window, pointing to remote calendar single-page web application. """ url = yield self.__urlMacros.parse(GUI_SETTINGS.adventCalendarBaseURL, params={'called': invokedFrom}) if not url: _logger.error('Invalid calendar URL') return browserHandlers = [createRequestHandler(handleRequestCommand)] def showBrowserWindow(): ctx = {'size': browserSize, 'handlers': browserHandlers, 'browserID': browserID, 'alias': VIEW_ALIAS.ADVENT_CALENDAR, 'showCloseBtn': False, 'showWaiting': True, 'showActionBtn': False} g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.ADVENT_CALENDAR, name=_genWindowName(browserID), ctx=ctx), scope=EVENT_BUS_SCOPE.LOBBY) _logger.debug('Calendar browser window shown (browserID=%d)' % browserID) yield self.browserCtrl.load(url=url, browserID=browserID, browserSize=browserSize, isAsync=False, useBrowserWindow=False, showBrowserCallback=showBrowserWindow, showCreateWaiting=False)
class BrowserController(Controller): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowser = False def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False, useWhitelisting = False): url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isDefault': isDefault, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn} texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and (self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE) app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, useWhitelisting) self.__browsers[browserID] = browser if self.__creatingBrowser: self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: self.__browsers[browserID].navigate(url) callback(browserID) return def __createDone(self, browserID): self.__creatingBrowser = False if len(self.__pendingBrowsers) > 0: ctx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(ctx) def __createBrowser(self, ctx): self.__creatingBrowser = True browserID = ctx['browserID'] self.__browsers[browserID].create() self.onBrowserAdded(browserID) def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) self.__createDone(browserID) def browserAsyncCallback(url, isLoaded): self.__clearCallback(browserID) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser async request url was not loaded!', url) self.__createDone(browserID) if ctx['isAsync']: self.__browsersCallbacks[browserID] = (None, browserAsyncCallback) self.__browsers[browserID].onLoadEnd += browserAsyncCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onReady += browserCallback return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: self.__browsers[browserID].onReady -= ready if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class BrowserController(Controller, AppRef): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onBattleStarted(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, background = None, isDefault = True, callback = None): url = url or GUI_SETTINGS.browser.url suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE background = background or BROWSER.BACKGROUND if browserID not in self.__browsers: browserID = self.__browserIDGenerator.next() texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE self.__browsers[browserID] = WebBrowser(browserID, self.app, texture, size, url, backgroundUrl=background) self.onBrowserAdded(browserID) ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isDefault': isDefault, 'isAsync': isAsync} def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) if isAsync: self.__browsersCallbacks[browserID] = (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onLoadStart += browserCallback callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): if browserID in self.__browsersCallbacks: loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: self.__browsers[browserID].onLoadStart -= loadStart if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): self.app.fireEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)