class ExternalLinksHandler(IExternalLinksController): def __init__(self): super(ExternalLinksHandler, self).__init__() self.__urlMacros = None return def init(self): self.__urlMacros = URLMacros() 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.__urlMacros is not None: self.__urlMacros.clear() self.__urlMacros = 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.__urlMacros.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 _handleParsedURL(self, event): self.__openParsedUrl(event.url) 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 _handleFrontlineChangesURL(self, _): self.__openParsedUrl('frontlineChangesURL') def _handleTokenShopURL(self, event): self.__openParsedUrl('tokenShopURL', event.params) def _handleTechTreeNewsURL(self, event): self.__openParsedUrl('techTreeUpdateNewsURL', event.params)
class ExternalLinksHandler(IExternalLinksController): __loginManager = dependency.descriptor(ILoginManager) def __init__(self): super(ExternalLinksHandler, self).__init__() self.__urlMacros = None self.__linksHandlers = None return def init(self): self.__urlMacros = URLMacros() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: _logger.error('Handler is not found %s %s', eventType, handlerName) continue if not callable(handler): _logger.error('Handler is invalid %s %s %r', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMacros is not None: self.__urlMacros.clear() self.__urlMacros = 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: _logger.error('URL is empty %r', url) return handled = False for handler in self._getHandlers(): handled = handler.handle(url) if handled: break if not handled: _logger.error('Cant handle external link: %s', url) @async @process def getURL(self, name, params=None, callback=lambda *args: None): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMacros.parse(str(urlSettings), params) else: url = yield lambda callback: callback('') callback(url) def externalAllowed(self, url): for handler in self._getHandlers(): result = handler.checkHandle(url) if result.handled: return result.externalAllowed return False 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 _handleParsedURL(self, event): self.__openParsedUrl(event.url) 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 _handleClanRulesURL(self, _): self.__openParsedUrl('clanRulesURL') 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 _handleFrontlineChangesURL(self, _): self.__openParsedUrl('frontlineChangesURL') def _handleTokenShopURL(self, event): self.__openParsedUrl('tokenShopURL', event.params) def _getHandlers(self): if not self.__linksHandlers: self.__linksHandlers = [] if self.__loginManager.isWgcSteam: self.__linksHandlers.append(external.PremShopLinksHandler()) self.__linksHandlers.append( external.AddPlatformTagLinksHandler()) self.__linksHandlers.append( external.PremShopLinksForArgsUrlHandler()) self.__linksHandlers.append( external.AddPlatformTagLinksToArgsUrlHandler()) self.__linksHandlers.append(external.OpenBrowserHandler()) return self.__linksHandlers
class PromoController(IPromoController): __browserCtrl = dependency.descriptor(IBrowserController) __notificationsCtrl = dependency.descriptor(IEventsNotificationsController) __webController = dependency.descriptor(IWebController) __settingsCore = dependency.descriptor(ISettingsCore) __lobbyContext = dependency.descriptor(ILobbyContext) __logger = dependency.descriptor(IPromoLogger) __bootcamp = dependency.descriptor(IBootcampController) def __init__(self): super(PromoController, self).__init__() self.__urlMacros = URLMacros() self.__externalCloseCallback = None self.__isLobbyInited = False self.__pendingPromo = None self.__promoCount = 0 self.__lastUpdateTimeMark = 0 self.__promoData = None self.__waitingForWebBridgeData = False self.__battlesFromLastTeaser = 0 self.__wasInBattle = False self.__hasPendingTeaser = False self.__isPromoOpen = False self.__browserCreationCallbacks = {} self.__browserWatchers = {} self.__isInHangar = False self.__isTeaserOpen = False self.__checkIntervalInBattles = GUI_SETTINGS.checkPromoFrequencyInBattles self.__em = EventManager() self.onNewTeaserReceived = Event(self.__em) self.onPromoCountChanged = Event(self.__em) self.onTeaserShown = Event(self.__em) self.onTeaserClosed = 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.__needToGetTeasersInfo(): self.__updateWebBrgData() elif self.__hasPendingTeaser: self.__tryToShowTeaser() self.__notificationsCtrl.onEventNotificationsChanged += self.__onEventNotification if not isPopupsWindowsOpenDisabled(): self.__processPromo( self.__notificationsCtrl.getEventsNotifications()) self.app.loaderManager.onViewLoaded += self.__onViewLoaded @property def checkIntervalInBattles(self): return self.__checkIntervalInBattles 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, soundSpaceID='field_post') @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 isTeaserOpen(self): return self.__isTeaserOpen 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.__waitingForWebBridgeData: 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 __needToGetTeasersInfo(self): return True if self.__battlesFromLastTeaser == 0 else self.__checkIntervalInBattles > 0 and self.__battlesFromLastTeaser % self.__checkIntervalInBattles == 0 def __onTeaserClosed(self, byUser=False): self.__isTeaserOpen = False self.onTeaserClosed() 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.__waitingForWebBridgeData = True response = yield self.__webController.sendRequest(ctx=ctx) self.__waitingForWebBridgeData = False if response.isSuccess(): self.__updateTeaserData(ctx.getDataObj(response.getData())) elif self.__hasPendingTeaser: self.__tryToShowTeaser() 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 self.onTeaserShown() yield self.__webController.sendRequest( PromoSendTeaserShownRequestCtx(promoID)) def __tryToShowTeaser(self): if self.__isLobbyInited and self.__isInHangar and not self.__waitingForWebBridgeData: 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.__isInHangar = False self.__isPromoOpen = False self.__externalCloseCallback = None self.__isTeaserOpen = False self.__notificationsCtrl.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.__waitingForWebBridgeData: 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, soundSpaceID=None): promoUrl = yield self.__urlMacros.parse(url) self.__registerLoadingCallback(promoUrl, loadingCallback) _showBrowserView(promoUrl, self.__onPromoClosed, soundSpaceID=soundSpaceID) 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 GameWindowController(IGameWindowController): eventsCache = dependency.descriptor(IEventsCache) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): self.__urlMacros = URLMacros() self.__isLobbyInited = False super(GameWindowController, self).__init__() def fini(self): self.__urlMacros.clear() self.__urlMacros = None self.hideWindow() super(GameWindowController, self).fini() return def onLobbyInited(self, event): self.__isLobbyInited = True self._addListeners() def onAvatarBecomePlayer(self): self._removeListeners() if self.__isLobbyInited: self.hideWindow() self.__isLobbyInited = False super(GameWindowController, self).onAvatarBecomePlayer() def onDisconnected(self): self.__isLobbyInited = False self._removeListeners() self.hideWindow() super(GameWindowController, self).onDisconnected() def hideWindow(self): raise NotImplementedError def showWindow(self, url=None, invokedFrom=None): self.hideWindow() self._showWindow(url, invokedFrom) @async @process def getUrl(self, callback=lambda *args: None): url = yield self.__urlMacros.parse(self._getUrl()) callback(url) def _addListeners(self): self.eventsCache.onSyncCompleted += self._onSyncCompleted def _removeListeners(self): self.eventsCache.onSyncCompleted -= self._onSyncCompleted def _onSyncCompleted(self, *_): pass @process def _showWindow(self, url, invokedFrom=None): if url is None: url = yield self.getUrl() if not url: return self._openWindow(url, invokedFrom) return def _openWindow(self, url, invokedFrom=None): raise NotImplementedError
class BrowserController(IBrowserController): 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 = URLMacros() 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() BigWorld.destroyBrowser() def onDisconnected(self): self.__stop() BigWorld.destroyBrowser() def onLobbyStarted(self, ctx): BigWorld.createBrowser() 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 not isinstance(browserID, 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: appLoader = dependency.instance(IAppLoader) app = appLoader.getApp() if app is None: raise SoftException('Application can not be None') browser = WebBrowser(webBrowserID, app, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): _logger.info('CTRL: Queueing a browser creation: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: _logger.info( 'CTRL: Re-queuing a browser creation, overriding: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: _logger.info('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.info('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.info('CTRL: Finished creating a browser: %r', 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.info('CTRL: Creating a browser: %r - %s', browserID, ctx['url']) self.__creatingBrowserID = browserID browser = self.__browsers[browserID] if not browser.create(): _logger.info('CTRL: Failed the create step: %r', browserID) self.delBrowser(browserID) self.__tryCreateNextPendingBrowser() return else: self.onBrowserAdded(browserID) def createNextBrowser(): _logger.info( 'CTRL: Triggering create of next browser from: %r', browserID) creation = self.__browserCreationCallbacks.pop(browserID, None) if creation is not None: self.__browsers[ browserID].onCanCreateNewBrowser -= creation self.__tryCreateNextPendingBrowser() return def failedCreationCallback(url): _logger.info('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.info('CTRL: Ready to show: %r isLoaded: %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.info('CTRL: Showing a browser: %r - %s', browserID, ctx['url']) if ctx.get('showWindow'): alias = ctx['alias'] g_eventBus.handleEvent( LoadViewEvent(SFViewLoadParams(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 = URLMacros() 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: _logger.error( 'Attempting to open internal browser, but browseris not exist. External browser will be opened: %r', linkToOpen) _logger.debug('Open browser: %r', 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) _logger.debug('Requesting login RSS news: %s', 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) _logger.debug('RSS feed received, entries count %d', 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): 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: _logger.exception('Invalid RSS entry description: %r, %r', entryData, description) return return { 'id': entryData.get('id', str(uuid.uuid4())), 'link': entryData.get('link'), 'description': encodeUtf8(description) }
class VehiclePreviewBuyingPanel(VehiclePreviewBuyingPanelMeta): appLoader = dependency.descriptor(IAppLoader) _itemsCache = dependency.descriptor(IItemsCache) _goodiesCache = dependency.descriptor(IGoodiesCache) _comparisonBasket = dependency.descriptor(IVehicleComparisonBasket) _tradeIn = dependency.descriptor(ITradeInController) _restores = dependency.descriptor(IRestoreController) _heroTanks = dependency.descriptor(IHeroTankController) _lobbyContext = dependency.descriptor(ILobbyContext) _marathonsCtrl = dependency.descriptor(IMarathonEventsController) __calendarController = dependency.descriptor(ICalendarController) __linksCtrl = dependency.descriptor(IExternalLinksController) def __init__(self, skipConfirm=False): super(VehiclePreviewBuyingPanel, self).__init__() heroTankCD = self._heroTanks.getCurrentTankCD() self._vehicleCD = g_currentPreviewVehicle.item.intCD self._vehicleLevel = g_currentPreviewVehicle.item.level self._actionType = None self._skipConfirm = skipConfirm self._disableBuyButton = False self._marathonEvent = None self.__previewDP = DefaultVehPreviewDataProvider() self.__isHeroTank = heroTankCD and heroTankCD == self._vehicleCD self.__price = None self.__title = None self.__description = None self.__items = None self.__offers = None self.__currentOffer = None self.__styleByGroup = {} self.__vehicleByGroup = {} self.__endTime = None self.__oldPrice = MONEY_UNDEFINED self.__buyParams = None self.__backAlias = None self.__backCallback = None self.__timeCallbackID = None self.__timeLeftIcon = icons.makeImageTag( RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON, 16, 16) self.__cachedVehiclesVOs = None self.__cachedItemsVOs = None self.__cachedCollapsedItemsVOs = None self.__couponInfo = None self.__hasSSEDiscount = False self.__urlMacros = URLMacros() g_techTreeDP.load() return def onBuyOrResearchClick(self): vehicle = g_currentPreviewVehicle.item shopPackage = self.__items is not None and self.__couponInfo is None frontlineCouponPackage = self.__couponInfo is not None and self.__couponInfo.selected if self._marathonEvent: self.__purchaseMarathonPackage() elif shopPackage or frontlineCouponPackage: self.__purchasePackage() elif self.__offers is not None: self.__purchaseOffer() elif self.__isHeroTank: self.__purchaseHeroTank() elif canBuyGoldForVehicleThroughWeb(vehicle): self.__purchaseSingleVehicle(vehicle) else: self.__research() return def onCouponSelected(self, isActive): if self.__couponInfo: self.__couponInfo.selected = isActive if isActive: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.active()) elif self.__hasSSEDiscount: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.inactive_add_discount()) else: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.inactive()) self.__update() def setMarathonEvent(self, prefix): self._marathonEvent = self._marathonsCtrl.getMarathon(prefix) def setTimerData(self, endTime): if self.__couponInfo is not None: return else: if endTime is not None: self.__endTime = endTime self.__onLeftTimeUpdated() self.__updateBtnState() return def setInfoTooltip(self): tooltip = self._marathonEvent.getVehiclePreviewTitleTooltip() self.as_setSetTitleTooltipS(tooltip) def setBuyParams(self, buyParams): self.__buyParams = buyParams def setBackAlias(self, backAlias): self.__backAlias = backAlias def setBackCallback(self, backCallback): self.__backCallback = backCallback def setIsHeroTank(self, isHero): self.__isHeroTank = isHero def setPackItems(self, packItems, price, oldPrice, title): self.__title = title if title is not None else '' self.__price = price self.__hasSSEDiscount = oldPrice != MONEY_UNDEFINED self.__oldPrice = oldPrice self.__items = packItems self.__styleByGroup.clear() self.__vehicleByGroup.clear() vehiclesItems, items = self.__previewDP.separateItemsPack(self.__items) for item in items: if item.type in ItemPackTypeGroup.STYLE and item.groupID not in self.__styleByGroup: self.__styleByGroup[item.groupID] = item.id if item.type in ItemPackTypeGroup.DISCOUNT: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.active()) self.__couponInfo = _CouponData(item=item, selected=True) self.as_setCouponS( self.__previewDP.packCouponData( self.__items, self.__price.get(Currency.GOLD))) if not self.__oldPrice: self.__oldPrice = self.__price for vehicleItem in vehiclesItems: self.__vehicleByGroup[vehicleItem.id] = vehicleItem.groupID vehiclesVOs, itemsVOs, collapseItemsVOs = self.__previewDP.getItemsPackData( g_currentPreviewVehicle.item, items, vehiclesItems) self.__cachedVehiclesVOs = vehiclesVOs self.__cachedItemsVOs = itemsVOs self.__cachedCollapsedItemsVOs = collapseItemsVOs self.__update() return def onCarouselVehicleSelected(self, intCD): self._vehicleCD = intCD g_currentPreviewVehicle.selectVehicle(intCD) def setOffers(self, offers, title, description): self.__offers = offers self.__title = title self.__description = description selectedID = getActiveOffer(self.__offers).id offersData = self.__previewDP.getOffersData( self.__offers, selectedID) if len(self.__offers) > 1 else [] self.as_setOffersDataS(offersData) self.onOfferSelected(selectedID) def onOfferSelected(self, offerID): self.__currentOffer = findFirst(lambda o: o.id == offerID, self.__offers) if self.__currentOffer: vehicle = g_currentPreviewVehicle.item crew = self.__currentOffer.crew g_eventBus.handleEvent( HasCtxEvent(ctx={ 'vehicleItems': [ItemPackEntry(id=vehicle.intCD, groupID=crew.groupID)], 'crewItems': [crew], 'offer': self.__currentOffer }, eventType=OFFER_CHANGED_EVENT)) self.__buyParams = self.__currentOffer.buyParams self.__price = self.__currentOffer.buyPrice self.as_setBuyDataS( self.__previewDP.getOffersBuyingPanelData(self.__getBtnData())) description = self.__description or self.__getCurrentOfferDescription( ) or {} self.as_setSetTitleTooltipS(makeTooltip(**description)) def showTooltip(self, intCD, itemType): toolTipMgr = self.appLoader.getApp().getToolTipMgr() if itemType == BOX_TYPE: toolTipMgr.onCreateComplexTooltip( makeTooltip(TOOLTIPS.VEHICLEPREVIEW_BOXTOOLTIP_HEADER, TOOLTIPS.VEHICLEPREVIEW_BOXTOOLTIP_BODY), 'INFO') return try: try: itemId = int(intCD) except ValueError: itemId = intCD rawItem = [ item for item in self.__items if item.id == itemId and item.type == itemType ][0] item = lookupItem(rawItem, self._itemsCache, self._goodiesCache) showItemTooltip(toolTipMgr, rawItem, item) except IndexError: return def updateData(self, useCompactData): self.__update(collapseItems=False) def _populate(self): super(VehiclePreviewBuyingPanel, self)._populate() g_clientUpdateManager.addMoneyCallback(self.__updateBtnState) g_clientUpdateManager.addCallbacks({ 'stats.freeXP': self.__updateBtnState, 'inventory': self.__updateBtnState, 'serverSettings.blueprints_config': self.__onBlueprintsModeChanged }) g_currentPreviewVehicle.onVehicleUnlocked += self.__updateBtnState g_currentPreviewVehicle.onChanged += self.__onVehicleChanged self._heroTanks.onUpdated += self.__updateBtnState self._restores.onRestoreChangeNotify += self.__onRestoreChanged self._lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingsChanged self.addListener(CameraRelatedEvents.VEHICLE_LOADING, self.__onVehicleLoading) def _dispose(self): g_clientUpdateManager.removeObjectCallbacks(self) g_currentPreviewVehicle.onVehicleUnlocked -= self.__updateBtnState g_currentPreviewVehicle.onChanged -= self.__onVehicleChanged self._heroTanks.onUpdated -= self.__updateBtnState self._restores.onRestoreChangeNotify -= self.__onRestoreChanged self._lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingsChanged self.removeListener(CameraRelatedEvents.VEHICLE_LOADING, self.__onVehicleLoading) self.__stopTimer() self.__styleByGroup.clear() self.__vehicleByGroup.clear() self.__urlMacros.clear() self.__urlMacros = None super(VehiclePreviewBuyingPanel, self)._dispose() return def __update(self, collapseItems=False): if self.__cachedVehiclesVOs: g_currentPreviewVehicle.selectVehicle( self.__cachedVehiclesVOs[0]['intCD']) self.as_setSetVehiclesDataS({'vehicles': self.__cachedVehiclesVOs}) if self.__couponInfo: self.__updateEnabledState(self.__cachedCollapsedItemsVOs, self.__couponInfo.selected) self.__updateEnabledState(self.__cachedItemsVOs, self.__couponInfo.selected) if collapseItems and self.__cachedCollapsedItemsVOs: self.as_setSetItemsDataS({'items': self.__cachedCollapsedItemsVOs}) elif self.__cachedItemsVOs: self.as_setSetItemsDataS({'items': self.__cachedItemsVOs}) self.__updateBtnState() def __getOfferByID(self, offerID): return findFirst(lambda o: o.buy_params['transactionID'] == offerID, self.__offers) def __isReferralWindow(self): return self.__backAlias == VIEW_ALIAS.REFERRAL_PROGRAM_WINDOW def __getConfirmationDialogKey(self): key = 'buyConfirmation' if self.__isReferralWindow(): key = 'referralReward' return key def __buyRequestConfirmation(self, key='buyConfirmation'): product = self.__title if self.__couponInfo is None else g_currentPreviewVehicle.item.shortUserName return DialogsInterface.showDialog(meta=I18nConfirmDialogMeta( key=key, messageCtx={ 'product': product, 'price': formatPrice(self.__getPackPrice(), reverse=True, useIcon=True) }, focusedID=DIALOG_BUTTON_ID.SUBMIT)) def __onVehicleLoading(self, ctxEvent): vehicle = g_currentPreviewVehicle.item if vehicle is None: return else: groupID = self.__vehicleByGroup.get(vehicle.intCD) if not ctxEvent.ctx.get( 'started') and groupID in self.__styleByGroup: customizationStyle = self.__styleByGroup[groupID] style = self._itemsCache.items.getItemByCD(customizationStyle) if style is not None and not style.isRentable: g_currentPreviewVehicle.previewStyle(style) return @process def __updateBtnState(self, *_): item = g_currentPreviewVehicle.item if item is None: return else: btnData = self.__getBtnData() self._actionType = self.__previewDP.getBuyType(item) if self.__items: buyingPanelData = self.__previewDP.getItemPackBuyingPanelData( btnData, self.__items, self.__couponInfo.selected if self.__couponInfo else False, self.__price.get(Currency.GOLD)) elif self.__offers: buyingPanelData = self.__previewDP.getOffersBuyingPanelData( btnData) else: buyingPanelData = self.__previewDP.getBuyingPanelData( item, btnData, self.__isHeroTank) buyingPanelData.update( {'isReferralEnabled': self.__isReferralWindow()}) hasExternalLink = yield self.__hasExternalLink() if hasExternalLink: btnIcon = backport.image( R.images.gui.maps.icons.library.buyInWeb()) buyingPanelData.update({ 'buyButtonIcon': btnIcon, 'buyButtonIconAlign': 'right' }) self.as_setBuyDataS(buyingPanelData) return def __onVehicleChanged(self, *_): if g_currentPreviewVehicle.isPresent(): self._vehicleCD = g_currentPreviewVehicle.item.intCD if not self.__price: self.__updateBtnState() def __onRestoreChanged(self, vehicles): if g_currentPreviewVehicle.isPresent(): if self._vehicleCD in vehicles: self.__updateBtnState() def __onServerSettingsChanged(self, diff): if self._lobbyContext.getServerSettings().isShopDataChangedInDiff( diff, 'isEnabled') or CollectorVehicleConsts.CONFIG_NAME in diff: self.__updateBtnState() def __onBlueprintsModeChanged(self, _): self.__updateBtnState() def __getBtnData(self): if self.__price is not None: return self.__getBtnDataPack() else: vehicle = g_currentPreviewVehicle.item if vehicle.isCollectible: return self.__getBtnDataCollectibleVehicle(vehicle) return self.__getBtnDataUnlockedVehicle( vehicle ) if vehicle.isUnlocked else self.__getBtnDataLockedVehicle( vehicle) def __getBtnDataPack(self): buyButtonTooltip = '' actionTooltip = None customOffer = None price = self.__getPackPrice() currency = price.getCurrency() walletAvailable = self.__walletAvailableForCurrency(currency) enabled = False if not walletAvailable: buyButtonTooltip = _buildBuyButtonTooltip('walletUnavailable') elif self._disableBuyButton: buyButtonTooltip = _buildBuyButtonTooltip('endTime') elif self.__price.isSet(currency): enabled = currency == Currency.GOLD or mayObtainForMoney( price) or mayObtainWithMoneyExchange(price) else: enabled = True if self.__currentOffer and self.__currentOffer.bestOffer and self.__currentOffer.eventType: actionTooltip = self.__getBestOfferTooltipData( self.__currentOffer.eventType) buttonIcon = None buttonIconAlign = None itemPrices = ItemPrice(price=price, defPrice=self.__oldPrice) specialData = getHeroTankPreviewParams() if self.__isHeroTank else None if specialData is not None and specialData.buyButtonLabel: buttonLabel = backport.text(specialData.buyButtonLabel) elif self.__isReferralWindow(): buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.obtain()) elif self._marathonEvent is not None: itemPrices = ITEM_PRICE_EMPTY buttonData = self._marathonEvent.getPreviewBuyBtnData() buttonLabel = buttonData['label'] enabled = buttonData['enabled'] buttonIcon = buttonData['btnIcon'] buttonIconAlign = buttonData['btnIconAlign'] buyButtonTooltip = buttonData['btnTooltip'] customOffer = buttonData['customOffer'] elif self.__items and self.__couponInfo is None: buttonLabel = backport.text(R.strings.vehicle_preview.buyingPanel. buyBtn.label.buyItemPack()) elif self.__offers and self.__currentOffer: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.rent()) self.__title = self.__getCurrentOfferTitle() else: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.buy()) isAction = self.__oldPrice.isDefined( ) and self.__oldPrice != self.__price or actionTooltip is not None or self.__couponInfo and self.__couponInfo.selected return _ButtonState(enabled=enabled, itemPrice=getItemPricesVO(itemPrices), label=buttonLabel, icon=buttonIcon, iconAlign=buttonIconAlign, isAction=isAction, actionTooltip=actionTooltip, tooltip=buyButtonTooltip, title=self.__title, isMoneyEnough=True, isUnlock=False, isPrevItemsUnlock=True, customOffer=customOffer, isShowSpecial=False) def __getPackPrice(self): if self.__couponInfo and self.__couponInfo.selected: discount = self.__couponInfo.discount currency = self.__price.getCurrency() if currency == Currency.GOLD: discountPrice = self.__price - discount return discountPrice.toNonNegative() return self.__price def __getBtnDataUnlockedVehicle(self, vehicle): money = self._itemsCache.items.stats.money money = self._tradeIn.addTradeInPriceIfNeeded(vehicle, money) buyButtonTooltip = '' actionTooltip = getActionPriceData(vehicle) exchangeRate = self._itemsCache.items.shop.exchangeRate priceType, price = getPriceTypeAndValue(vehicle, money, exchangeRate) itemPrice = chooseItemPriceVO(priceType, price) currency = price.getCurrency(byWeight=True) walletAvailable = self.__walletAvailableForCurrency(currency) buttonLabel = self.__getUnlockedVehicleBtnLabel(priceType) buttonIcon = None buttonIconAlign = None isAction = False minRentPricePackage = vehicle.getRentPackage() if minRentPricePackage: isAction = minRentPricePackage['rentPrice'] != minRentPricePackage[ 'defaultRentPrice'] elif not vehicle.isRestoreAvailable(): isAction = vehicle.buyPrices.getSum().isActionPrice() mayObtain = self.__isHeroTank or walletAvailable and vehicle.mayObtainWithMoneyExchange( money, exchangeRate) isBuyingAvailable = not vehicle.isHidden or vehicle.isRentable or vehicle.isRestorePossible( ) isMoneyEnough = True if not walletAvailable: buyButtonTooltip = _buildBuyButtonTooltip('walletUnavailable') elif not mayObtain and isBuyingAvailable: if currency == Currency.GOLD: mayObtain = True else: buyButtonTooltip = _buildBuyButtonTooltip('notEnoughCredits') isMoneyEnough = False if self._disableBuyButton or self.__isHeroTank and self._vehicleCD != self._heroTanks.getCurrentTankCD( ): mayObtain = False isMoneyEnough = False return _ButtonState(enabled=mayObtain, itemPrice=itemPrice, label=buttonLabel, icon=buttonIcon, iconAlign=buttonIconAlign, isAction=isAction, actionTooltip=actionTooltip, tooltip=buyButtonTooltip, title=self.__title, isMoneyEnough=isMoneyEnough, isUnlock=False, isPrevItemsUnlock=True, customOffer=None, isShowSpecial=False) def __getBtnDataCollectibleVehicle(self, vehicle): isVehicleCollectorEnabled = self._lobbyContext.getServerSettings( ).isCollectorVehicleEnabled() isNationUnlocked = vehicle_collector_helper.isAvailableForPurchase( vehicle) resultVO = self.__getBtnDataUnlockedVehicle(vehicle) if isVehicleCollectorEnabled and isNationUnlocked: return resultVO if not isVehicleCollectorEnabled: tooltip = TOOLTIPS_CONSTANTS.VEHICLE_COLLECTOR_DISABLED isSpecialTooltip = True else: key = 'notUnlockedNation' tooltip = makeTooltip( header=TOOLTIPS.vehiclepreview_buybutton_all(key, 'header'), body=_getCollectibleWarningStr( TOOLTIPS.vehiclepreview_buybutton_all(key, 'body'), vehicle)) if resultVO.isMoneyEnough else resultVO.tooltip isSpecialTooltip = False resultVO = resultVO._replace(enabled=False, tooltip=tooltip, isShowSpecial=isSpecialTooltip) return resultVO def __getBtnDataLockedVehicle(self, vehicle): stats = self._itemsCache.items.stats tooltip = '' buttonIcon = None buttonIconAlign = None nodeCD = vehicle.intCD _, isXpEnough = g_techTreeDP.isVehicleAvailableToUnlock( nodeCD, self._vehicleLevel) unlocks = self._itemsCache.items.stats.unlocks isNext2Unlock, unlockProps = g_techTreeDP.isNext2Unlock( nodeCD, unlocked=set(unlocks), xps=stats.vehiclesXPs, freeXP=stats.freeXP, level=self._vehicleLevel) isAvailableToUnlock = isXpEnough and isNext2Unlock if not isAvailableToUnlock: if not isXpEnough: tooltip = _buildBuyButtonTooltip('notEnoughXp') elif any((bool(cd in unlocks) for cd in g_techTreeDP.getTopLevel(nodeCD))): tooltip = _buildBuyButtonTooltip('parentModuleIsLocked') else: tooltip = _buildBuyButtonTooltip('parentVehicleIsLocked') specialData = getHeroTankPreviewParams() if self.__isHeroTank else None if specialData is not None and specialData.buyButtonLabel: buyLabel = backport.text(specialData.buyButtonLabel) else: buyLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.research()) return _ButtonState(enabled=isAvailableToUnlock, itemPrice=getItemUnlockPricesVO(unlockProps), label=buyLabel, icon=buttonIcon, iconAlign=buttonIconAlign, isAction=unlockProps.discount > 0, actionTooltip=None, tooltip=tooltip, title=self.__title, isMoneyEnough=isXpEnough, isUnlock=True, isPrevItemsUnlock=isNext2Unlock, customOffer=None, isShowSpecial=False) @staticmethod def __getBestOfferTooltipData(eventType=None): return VEHICLE_PREVIEW.BUYINGPANEL_OFFER_RENT_FRONTLINE_TOOLTIP_BEST_OFFER if eventType == 'frontline' else None def __getCurrentOfferTitle(self): if self.__offers and self.__currentOffer: if self.__currentOffer.eventType == 'frontline': firstRent = first(self.__currentOffer.rent) if len(self.__offers) > 1 or firstRent and firstRent.get( 'season') is not None: return _ms( backport.text(R.strings.vehicle_preview.buyingPanel. offer.rent.title.frontline.ordinal())) return _ms( backport.text(R.strings.vehicle_preview.buyingPanel.offer. rent.title.frontline.single_cycle()), cycles=self.__currentOffer.name) return self.__title def __getCurrentOfferDescription(self): return { 'header': backport.text(R.strings.vehicle_preview.buyingPanel.offer.rent. frontline.description.header()), 'body': backport.text(R.strings.vehicle_preview.buyingPanel.offer.rent. frontline.description.body.credits()) } if self.__currentOffer and self.__currentOffer.eventType == 'frontline' else None def __startTimer(self, interval): self.__stopTimer() self.__timeCallbackID = BigWorld.callback(interval, self.__onLeftTimeUpdated) def __stopTimer(self): if self.__timeCallbackID is not None: BigWorld.cancelCallback(self.__timeCallbackID) self.__timeCallbackID = None return def __setUsageLeftTime(self, leftTime): self.as_updateLeftTimeS(formattedTime='{} {}'.format( self.__timeLeftIcon, text_styles.tutorial( time_utils.getTillTimeString(leftTime, MENU.VEHICLEPREVIEW_TIMELEFT))), hasHoursAndMinutes=True) def __setShortLeftTime(self, leftTime): self.as_updateLeftTimeS(formattedTime='{} {}'.format( self.__timeLeftIcon, text_styles.tutorial( time_utils.getTillTimeString( leftTime, MENU.VEHICLEPREVIEW_TIMELEFTSHORT))), hasHoursAndMinutes=True) def __setDateLeftTime(self): tm = time_utils.getTimeStructInLocal(self.__endTime) monthName = backport.text( R.strings.menu.dateTime.months.num(tm.tm_mon)()) fmtValues = backport.text(R.strings.menu.dateTime.order(), day=tm.tm_mday, month=monthName, year=tm.tm_year) tooltip = makeTooltip( header=backport.text(R.strings.tooltips.vehiclePreview.shopPack. dateTimeTooltip.header()), body=backport.text(R.strings.tooltips.vehiclePreview.shopPack. dateTimeTooltip.body(), namePack=text_styles.neutral(self.__title), date=fmtValues)) self.as_setSetTitleTooltipS(tooltip) self.as_updateLeftTimeS(formattedTime='') def __timeOver(self): self.__endTime = None self._disableBuyButton = True formattedTime = '{} {}'.format( icons.makeImageTag(RES_ICONS.MAPS_ICONS_LIBRARY_ALERTICON2, vSpace=-2), text_styles.alert(MENU.VEHICLEPREVIEW_ENDTIME)) self.as_updateLeftTimeS(formattedTime=formattedTime) self.__updateBtnState() return def __onLeftTimeUpdated(self): leftTime = self.__endTime - time_utils.getServerUTCTime() self.__timeCallbackID = None if leftTime < 0: self.__timeOver() elif leftTime > time_utils.ONE_DAY: self.__setDateLeftTime() self.__startTimer(leftTime - time_utils.ONE_DAY) else: gmTime = time.gmtime(leftTime) if gmTime.tm_min == 0: self.__setShortLeftTime(leftTime) else: self.__setUsageLeftTime(leftTime) self.__startTimer(gmTime.tm_sec + 1) return @process def __purchasePackage(self): if self.__items is not None: product = self.__title if self.__couponInfo is None else g_currentPreviewVehicle.item.shortUserName price = self.__getPackPrice() if not mayObtainForMoney(price) and mayObtainWithMoneyExchange( price): isOk, _ = yield DialogsInterface.showDialog( ExchangeCreditsWebProductMeta(name=product, count=1, price=price.get( Currency.CREDITS))) if isOk: self.__purchasePackage() return return requestConfirmed = yield self.__buyRequestConfirmation( self.__getConfirmationDialogKey()) if requestConfirmed: if self.__isReferralWindow(): inventoryVehicle = self._itemsCache.items.getItemByCD( g_currentPreviewVehicle.item.intCD) showGetVehiclePage(inventoryVehicle, self.__buyParams) return if mayObtainForMoney(price): showBuyVehicleOverlay(self.__buyParams) elif price.get(Currency.GOLD, 0) > self._itemsCache.items.stats.gold: showBuyGoldForBundle(price.get(Currency.GOLD, 0), self.__buyParams) return def __purchaseOffer(self): rent = self.__currentOffer.rent cycles = [r['cycle'] for r in rent if r.get('cycle')] seasons = [r['season'] for r in rent if r.get('season')] showVehicleRentDialog( g_currentPreviewVehicle.item.intCD, RentType.SEASON_CYCLE_RENT if cycles else RentType.SEASON_RENT, cycles if cycles else seasons, GameSeasonType.EPIC if self.__currentOffer.eventType == 'frontline' else None, self.__currentOffer.buyPrice, self.__currentOffer.buyParams) return def __purchaseSingleVehicle(self, vehicle): event_dispatcher.showVehicleBuyDialog( vehicle, returnAlias=self.__backAlias, returnCallback=self.__backCallback) @process def __purchaseHeroTank(self): if self._heroTanks.isAdventHero(): self.__calendarController.showWindow( invokedFrom=CalendarInvokeOrigin.HANGAR) return shopUrl = self._heroTanks.getCurrentShopUrl() if shopUrl: event_dispatcher.showShop(shopUrl) else: url = yield self.__urlMacros.parse( self._heroTanks.getCurrentRelatedURL()) self.fireEvent( events.OpenLinkEvent(events.OpenLinkEvent.SPECIFIED, url=url)) @async @process def __hasExternalLink(self, callback=None): url = '' if self._marathonEvent: url = yield self._marathonEvent.getMarathonVehicleUrl() elif self.__isHeroTank: if not self._heroTanks.isAdventHero( ) and not self._heroTanks.getCurrentShopUrl(): url = self._heroTanks.getCurrentRelatedURL() callback(self.__linksCtrl.externalAllowed(url) if url else False) @process def __purchaseMarathonPackage(self): if self._marathonEvent.hasIgbLink(): url = yield self._marathonEvent.getMarathonVehicleUrlIgb() event_dispatcher.showShop(url) else: url = yield self._marathonEvent.getMarathonVehicleUrl() self.fireEvent( events.OpenLinkEvent(events.OpenLinkEvent.SPECIFIED, url=url)) def __research(self): if self._actionType == factory.UNLOCK_ITEM: unlockProps = g_techTreeDP.getUnlockProps(self._vehicleCD, self._vehicleLevel) factory.doAction(factory.UNLOCK_ITEM, self._vehicleCD, unlockProps, skipConfirm=self._skipConfirm) else: factory.doAction(factory.BUY_VEHICLE, self._vehicleCD, False, None, VIEW_ALIAS.VEHICLE_PREVIEW, self.__backAlias, self.__backCallback, skipConfirm=self._skipConfirm) return def __walletAvailableForCurrency(self, currency): return self._itemsCache.items.stats.currencyStatuses.get( currency) == WalletController.STATUS.AVAILABLE def __getUnlockedVehicleBtnLabel(self, priceType): specialData = getHeroTankPreviewParams() if self.__isHeroTank else None if specialData is not None and specialData.buyButtonLabel: buttonLabel = backport.text(specialData.buyButtonLabel) elif priceType == ActualPrice.RESTORE_PRICE: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.restore()) elif priceType == ActualPrice.RENT_PRICE: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.rent()) elif self.__isHeroTank and self._heroTanks.isAdventHero(): buttonLabel = backport.text(R.strings.vehicle_preview.buyingPanel. buyBtn.label.showAdventCalendar()) else: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.buy()) return buttonLabel @staticmethod def __updateEnabledState(collection, enabled): if collection is None: return else: for item in collection: if 'isEnabled' in item: item['isEnabled'] = enabled return
class InternalLinksHandler(IInternalLinksController): browserCtrl = dependency.descriptor(IBrowserController) def __init__(self): super(InternalLinksHandler, self).__init__() self.__urlMacros = None self._browserID = None return def init(self): self.__urlMacros = URLMacros() 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.__urlMacros is not None: self.__urlMacros.clear() self.__urlMacros = 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.__urlMacros.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)