2015-07-22 01:01:23 +02:00
"use strict" ; var Candy = function ( a , b ) { return a . about = { name : "Candy" , version : "2.0.0" } , a . init = function ( c , d ) { d . viewClass || ( d . viewClass = a . View ) , d . viewClass . init ( b ( "#candy" ) , d . view ) , a . Core . init ( c , d . core ) } , a } ( Candy || { } , jQuery ) ; Candy . Core = function ( a , b , c ) { var d , e = null , f = null , g = null , h = null , i = { } , j = ! 1 , k = { autojoin : void 0 , disconnectWithoutTabs : ! 0 , conferenceDomain : void 0 , debug : ! 1 , domains : null , hideDomainList : ! 1 , disableCoreNotifications : ! 1 , disableWindowUnload : ! 1 , presencePriority : 1 , resource : Candy . about . name , useParticipantRealJid : ! 1 , initialRosterVersion : null , initialRosterItems : [ ] } , l = function ( a , c ) { b . addNamespace ( a , c ) } , m = function ( ) { l ( "PRIVATE" , "jabber:iq:private" ) , l ( "BOOKMARKS" , "storage:bookmarks" ) , l ( "PRIVACY" , "jabber:iq:privacy" ) , l ( "DELAY" , "urn:xmpp:delay" ) , l ( "JABBER_DELAY" , "jabber:x:delay" ) , l ( "PUBSUB" , "http://jabber.org/protocol/pubsub" ) , l ( "CARBONS" , "urn:xmpp:carbons:2" ) } , n = function ( a ) { var c = b . getNodeFromJid ( a ) , d = b . getDomainFromJid ( a ) ; return c ? b . escapeNode ( c ) + "@" + d : d } ; return a . init = function ( d , g ) { f = d , c . extend ( ! 0 , k , g ) , k . debug && ( void 0 !== typeof window . console && void 0 !== typeof window . console . log && ( Function . prototype . bind && Candy . Util . getIeVersion ( ) > 8 ? a . log = Function . prototype . bind . call ( console . log , console ) : a . log = function ( ) { Function . prototype . apply . call ( console . log , console , arguments ) } ) , b . log = function ( a , c ) { var d , e ; switch ( a ) { case b . LogLevel . DEBUG : d = "DEBUG" , e = "log" ; break ; case b . LogLevel . INFO : d = "INFO" , e = "info" ; break ; case b . LogLevel . WARN : d = "WARN" , e = "info" ; break ; case b . LogLevel . ERROR : d = "ERROR" , e = "error" ; break ; case b . LogLevel . FATAL : d = "FATAL" , e = "error" } console [ e ] ( "[Strophe][" + d + "]: " + c ) } , a . log ( "[Init] Debugging enabled" ) ) , m ( ) , h = new Candy . Core . ChatRoster , e = new b . Connection ( f ) , e . rawInput = a . rawInput . bind ( a ) , e . rawOutput = a . rawOutput . bind ( a ) , e . caps . node = "https://candy-chat.github.io/candy/" , k . disableWindowUnload || ( window . onbeforeunload = a . onWindowUnload ) } , a . registerEventHandlers = function ( ) { a . addHandler ( a . Event . Jabber . Version , b . NS . VERSION , "iq" ) , a . addHandler ( a . Event . Jabber . Presence , null , "presence" ) , a . addHandler ( a . Event . Jabber . Message , null , "message" ) , a . addHandler ( a . Event . Jabber . Bookmarks , b . NS . PRIVATE , "iq" ) , a . addHandler ( a . Event . Jabber . Room . Disco , b . NS . DISCO _INFO , "iq" , "result" ) , a . addHandler ( e . disco . _onDiscoInfo . bind ( e . disco ) , b . NS . DISCO _INFO , "iq" , "get" ) , a . addHandler ( e . disco . _onDiscoItems . bind ( e . disco ) , b . NS . DISCO _ITEMS , "iq" , "get" ) , a . addHandler ( e . caps . _delegateCapabilities . bind ( e . caps ) , b . NS . CAPS ) } , a . connect = function ( d , f , h ) { if ( e . reset ( ) , a . registerEventHandlers ( ) , c ( Candy ) . triggerHandler ( "candy:core.before-connect" , { connection : e } ) , j = j ? ! 0 : d && d . indexOf ( "@" ) < 0 , d && f ) { var i = b . getResourceFromJid ( d ) ; i && ( k . resource = i ) , e . connect ( n ( d ) + "/" + k . resource , f , Candy . Core . Event . Strophe . Connect ) , g = h ? new a . ChatUser ( d , h ) : new a . ChatUser ( d , b . getNodeFromJid ( d ) ) } else d && h ? ( e . connect ( n ( d ) + "/" + k . resource , null , Candy . Core . Event . Strophe . Connect ) , g = new a . ChatUser ( null , h ) ) : d ? Candy . Core . Event . Login ( d ) : Candy . Core . Event . Login ( ) } , a . attach = function ( c , d , f , h ) { g = h ? new a . ChatUser ( c , h ) : new a . ChatUser ( c , b . getNodeFromJid ( c ) ) , e . reset ( ) , a . registerEventHandlers ( ) , e . attach ( c , d , f , Candy . Core . Event . Strophe . Connect ) } , a . disconnect = function ( ) { e . connected && e . disconnect ( ) } , a . addHandler = function ( a , b , c , d , f , g , h ) { return e . addHandler ( a , b , c , d , f , g , h ) } , a . getRoster = function ( ) { return h } , a . getUser = function ( ) { return g } , a . setUser = function ( a ) { g = a } , a . getConnection = function ( ) { return e } , a . removeRoom = function ( a ) { delete i [ a ] } , a . getRooms = function ( ) { return i } , a . getStropheStatus = function ( ) { return d } , a . setStropheStatus = function ( a ) { d = a } , a . isAnonymousConnection = function ( ) { return j } , a . getOptions = function ( ) { return k } , a . getRoom = function ( a ) { return i [ a ] ? i [ a ] : null } , a . onWindowUnload = function ( ) { e . options . sync = ! 0 , a . disconnect ( ) , e . flush ( ) } , a . rawInput = function ( a ) { this . log ( "RECV: " + a ) } , a . rawOutput = function ( a ) { this . log ( "SENT: " + a ) } , a . log = function ( ) { } , a . warn = function ( ) { Function . prototype . apply . call ( console . warn , console , arguments ) } , a . error = function ( ) { Function . prototype . apply . call ( console . error , console , arguments ) } , a } ( Candy . Core || { } , Strophe , jQuery ) , Candy . View = function ( a , b ) { var c = { container : null , roomJid : null } , d = { language : "en" , assets : "res/" , messages : { limit : 2e3 , remove : 500 } ,
d . children ( 'sent[xmlns="' + b . NS . CARBONS + '"]' ) . length > 0 && ( e = ! 0 , d = c ( d . children ( "sent" ) . children ( "forwarded" ) . children ( "message" ) ) , f = Candy . Util . unescapeJid ( d . attr ( "to" ) ) ) , d . children ( 'received[xmlns="' + b . NS . CARBONS + '"]' ) . length > 0 && ( e = ! 0 , d = c ( d . children ( "received" ) . children ( "forwarded" ) . children ( "message" ) ) , f = Candy . Util . unescapeJid ( d . attr ( "from" ) ) ) ; var g , h , i , j , k , l , m ; if ( d . children ( "subject" ) . length > 0 && d . children ( "subject" ) . text ( ) . length > 0 && "groupchat" === d . attr ( "type" ) ) g = Candy . Util . unescapeJid ( b . getBareJidFromJid ( f ) ) , i = Candy . Util . unescapeJid ( b . getBareJidFromJid ( d . attr ( "from" ) ) ) , h = b . getNodeFromJid ( g ) , j = { from : i , name : b . getNodeFromJid ( i ) , body : d . children ( "subject" ) . text ( ) , type : "subject" } ; else if ( "error" === d . attr ( "type" ) ) { var n = d . children ( "error" ) ; n . children ( "text" ) . length > 0 && ( g = f , h = b . getNodeFromJid ( g ) , j = { from : d . attr ( "from" ) , type : "info" , body : n . children ( "text" ) . text ( ) } ) } else { if ( ! ( d . children ( "body" ) . length > 0 ) ) return ! 0 ; if ( "chat" === d . attr ( "type" ) || "normal" === d . attr ( "type" ) ) { i = Candy . Util . unescapeJid ( d . attr ( "from" ) ) ; var o = b . getBareJidFromJid ( f ) , p = b . getBareJidFromJid ( i ) , q = ! Candy . Core . getRoom ( o ) ; if ( q ) { g = o ; var r = Candy . Core . getRoster ( ) . get ( o ) ; h = r ? r . getName ( ) : b . getNodeFromJid ( o ) , m = p === Candy . Core . getUser ( ) . getJid ( ) ? Candy . Core . getUser ( ) : Candy . Core . getRoster ( ) . get ( p ) , k = m ? m . getName ( ) : b . getNodeFromJid ( i ) } else g = f , l = Candy . Core . getRoom ( Candy . Util . unescapeJid ( b . getBareJidFromJid ( i ) ) ) , m = l . getRoster ( ) . get ( i ) , k = m ? m . getName ( ) : b . getResourceFromJid ( i ) , h = k ; j = { from : i , name : k , body : d . children ( "body" ) . text ( ) , type : d . attr ( "type" ) , isNoConferenceRoomJid : q } } else { i = Candy . Util . unescapeJid ( d . attr ( "from" ) ) , g = Candy . Util . unescapeJid ( b . getBareJidFromJid ( f ) ) ; var s = b . getResourceFromJid ( f ) ; if ( s ) l = Candy . Core . getRoom ( g ) , h = l . getName ( ) , m = s === Candy . Core . getUser ( ) . getNick ( ) ? Candy . Core . getUser ( ) : l . getRoster ( ) . get ( i ) , k = m ? m . getName ( ) : b . unescapeNode ( s ) , j = { from : g , name : k , body : d . children ( "body" ) . text ( ) , type : d . attr ( "type" ) } ; else { if ( ! Candy . Core . getRooms ( ) [ f ] ) return ! 0 ; h = "" , j = { from : g , name : "" , body : d . children ( "body" ) . text ( ) , type : "info" } } } var t = d . children ( 'html[xmlns="' + b . NS . XHTML _IM + '"]' ) ; if ( t . length > 0 ) { var u = c ( c ( "<div>" ) . append ( t . children ( "body" ) . first ( ) . contents ( ) ) . html ( ) ) ; j . xhtmlMessage = u } a . Jabber . Room . _checkForChatStateNotification ( d , g , k ) } var v = d . children ( 'delay[xmlns="' + b . NS . DELAY + '"]' ) ; j . delay = ! 1 , v . length < 1 ? v = d . children ( 'x[xmlns="' + b . NS . JABBER _DELAY + '"]' ) : j . delay = ! 0 ; var w = v . length > 0 ? v . attr ( "stamp" ) : ( new Date ) . toISOString ( ) ; return c ( Candy ) . triggerHandler ( "candy:core.message" , { roomJid : g , roomName : h , message : j , timestamp : w , carbon : e , stanza : d } ) , ! 0 } , _checkForChatStateNotification : function ( a , b , d ) { var e = a . children ( '*[xmlns="http://jabber.org/protocol/chatstates"]' ) ; e . length > 0 && c ( Candy ) . triggerHandler ( "candy:core:message:chatstate" , { name : d , roomJid : b , chatstate : e [ 0 ] . tagName } ) } } } , a } ( Candy . Core . Event || { } , Strophe , jQuery ) , Candy . View . Observer = function ( a , b ) { var c = ! 0 ; return a . Chat = { Connection : function ( a , d ) { var e = "candy:view.connection.status-" + d . status ; if ( b ( Candy ) . triggerHandler ( e ) === ! 1 ) return ! 1 ; switch ( d . status ) { case Strophe . Status . CONNECTING : case Strophe . Status . AUTHENTICATING : Candy . View . Pane . Chat . Modal . show ( b . i18n . _ ( "statusConnecting" ) , ! 1 , ! 0 ) ; break ; case Strophe . Status . ATTACHED : case Strophe . Status . CONNECTED : c === ! 0 && ( Candy . View . Pane . Chat . Modal . show ( b . i18n . _ ( "statusConnected" ) ) , Candy . View . Pane . Chat . Modal . hide ( ) ) ; break ; case Strophe . Status . DISCONNECTING : Candy . View . Pane . Chat . Modal . show ( b . i18n . _ ( "statusDisconnecting" ) , ! 1 , ! 0 ) ; break ; case Strophe . Status . DISCONNECTED : var f = Candy . Core . isAnonymousConnection ( ) ? Strophe . getDomainFromJid ( Candy . Core . getUser ( ) . getJid ( ) ) : null ; Candy . View . Pane . Chat . Modal . showLoginForm ( b . i18n . _ ( "statusDisconnected" ) , f ) ; break ; case Strophe . Status . AUTHFAIL : Candy . View . Pane . Chat . Modal . showLoginForm ( b . i18n . _ ( "statusAuthfail" ) ) ; break ; default : Candy . View . Pane . Chat . Modal . show ( b . i18n . _ ( "status" , d . status ) ) } } , Message : function ( a , b ) { "message" === b . type ? Candy . View . Pane . Chat . adminMessage ( b . subject || "" , b . message ) : ( "chat" === b . type || "groupchat" === b . type ) && Candy . View . Pane . Chat . onInfoMessage ( Candy . View . getCurrent ( ) . roomJid , b . subject || "" , b . message ) } } , a . Presence = { update : function ( c , d ) { if ( "leave" === d . type ) { var e = Candy . View . Pane
roomJid : c , user : d , action : e , element : j } ; if ( b ( Candy ) . triggerHandler ( "candy:view.roster.before-update" , k ) , "join" === e ) i = 1 , j . length < 1 ? ( a . Roster . _insertUser ( c , g , d , h , f ) , a . Roster . showJoinAnimation ( d , h , g , c , f ) ) : ( i = 0 , j . remove ( ) , a . Roster . _insertUser ( c , g , d , h , f ) , void 0 !== f && d . getNick ( ) === f . getNick ( ) && a . Room . getUser ( c ) && a . Chat . Toolbar . update ( c ) ) , void 0 !== f && f . getNick ( ) === d . getNick ( ) ? a . Room . setUser ( c , d ) : b ( "#user-" + g + "-" + h ) . click ( a . Roster . userClick ) , b ( "#user-" + g + "-" + h + " .context" ) . click ( function ( b ) { a . Chat . Context . show ( b . currentTarget , c , d ) , b . stopPropagation ( ) } ) , void 0 !== f && f . isInPrivacyList ( "ignore" , d . getJid ( ) ) && Candy . View . Pane . Room . addIgnoreIcon ( c , d . getJid ( ) ) ; else if ( "leave" === e ) a . Roster . leaveAnimation ( "user-" + g + "-" + h ) , "chat" === a . Chat . rooms [ c ] . type ? a . Chat . onInfoMessage ( c , null , b . i18n . _ ( "userLeftRoom" , [ d . getNick ( ) ] ) ) : a . Chat . infoMessage ( c , null , b . i18n . _ ( "userLeftRoom" , [ d . getNick ( ) ] ) , "" ) ; else if ( "nickchange" === e ) { i = 0 , a . Roster . changeNick ( g , d ) , a . Room . changeDataUserJidIfUserIsMe ( g , d ) , a . PrivateRoom . changeNick ( c , d ) ; var l = b . i18n . _ ( "userChangedNick" , [ d . getPreviousNick ( ) , d . getNick ( ) ] ) ; a . Chat . infoMessage ( c , null , l ) } else "kick" === e ? ( a . Roster . leaveAnimation ( "user-" + g + "-" + h ) , a . Chat . onInfoMessage ( c , null , b . i18n . _ ( "userHasBeenKickedFromRoom" , [ d . getNick ( ) ] ) ) ) : "ban" === e && ( a . Roster . leaveAnimation ( "user-" + g + "-" + h ) , a . Chat . onInfoMessage ( c , null , b . i18n . _ ( "userHasBeenBannedFromRoom" , [ d . getNick ( ) ] ) ) ) ; Candy . View . Pane . Chat . rooms [ c ] . usercount += i , c === Candy . View . getCurrent ( ) . roomJid && Candy . View . Pane . Chat . Toolbar . updateUsercount ( Candy . View . Pane . Chat . rooms [ c ] . usercount ) , k . element = b ( "#user-" + g + "-" + h ) , b ( Candy ) . triggerHandler ( "candy:view.roster.after-update" , k ) } , _insertUser : function ( c , d , e , f , g ) { var h = e . getContact ( ) , i = Mustache . to _html ( Candy . View . Template . Roster . user , { roomId : d , userId : f , userJid : e . getJid ( ) , realJid : e . getRealJid ( ) , status : e . getStatus ( ) , contact _status : h ? h . getStatus ( ) : "unavailable" , nick : e . getNick ( ) , displayNick : Candy . Util . crop ( e . getNick ( ) , Candy . View . getOptions ( ) . crop . roster . nickname ) , role : e . getRole ( ) , affiliation : e . getAffiliation ( ) , me : void 0 !== g && e . getNick ( ) === g . getNick ( ) , tooltipRole : b . i18n . _ ( "tooltipRole" ) , tooltipIgnored : b . i18n . _ ( "tooltipIgnored" ) } ) , j = ! 1 , k = a . Room . getPane ( c , ".roster-pane" ) ; if ( k . children ( ) . length > 0 ) { var l = a . Roster . _userSortCompare ( e . getNick ( ) , e . getStatus ( ) ) ; k . children ( ) . each ( function ( ) { var c = b ( this ) ; return a . Roster . _userSortCompare ( c . attr ( "data-nick" ) , c . attr ( "data-status" ) ) > l ? ( c . before ( i ) , j = ! 0 , ! 1 ) : ! 0 } ) } j || k . append ( i ) } , _userSortCompare : function ( a , b ) { var c ; switch ( b ) { case "available" : c = 1 ; break ; case "unavailable" : c = 9 ; break ; default : c = 8 } return c + a . toUpperCase ( ) } , userClick : function ( ) { var c = b ( this ) , d = c . attr ( "data-real-jid" ) , e = Candy . Core . getOptions ( ) . useParticipantRealJid && void 0 !== d && null !== d && "" !== d , f = e && d ? Strophe . getBareJidFromJid ( d ) : c . attr ( "data-jid" ) ; a . PrivateRoom . open ( f , c . attr ( "data-nick" ) , ! 0 , e ) } , showJoinAnimation : function ( c , d , e , f , g ) { var h = "user-" + e + "-" + d , i = b ( "#" + h ) ; c . getPreviousNick ( ) && i && i . is ( ":visible" ) !== ! 1 || ( a . Roster . joinAnimation ( h ) , void 0 !== g && c . getNick ( ) !== g . getNick ( ) && a . Room . getUser ( f ) && ( "chat" === a . Chat . rooms [ f ] . type ? a . Chat . onInfoMessage ( f , null , b . i18n . _ ( "userJoinedRoom" , [ c . getNick ( ) ] ) ) : a . Chat . infoMessage ( f , null , b . i18n . _ ( "userJoinedRoom" , [ c . getNick ( ) ] ) ) ) ) } , joinAnimation : function ( a ) { b ( "#" + a ) . stop ( ! 0 ) . slideDown ( "normal" , function ( ) { b ( this ) . animate ( { opacity : 1 } ) } ) } , leaveAnimation : function ( a ) { b ( "#" + a ) . stop ( ! 0 ) . attr ( "id" , "#" + a + "-leaving" ) . animate ( { opacity : 0 } , { complete : function ( ) { b ( this ) . slideUp ( "normal" , function ( ) { b ( this ) . remove ( ) } ) } } ) } , changeNick : function ( a , c ) { Candy . Core . log ( "[View:Pane:Roster] changeNick" ) ; var d = Strophe . getBareJidFromJid ( c . getJid ( ) ) + "/" + c . getPreviousNick ( ) , e = "user-" + a + "-" + Candy . Util . jidToId ( d ) , f = b ( "#" + e ) ; f . attr ( "data-nick" , c . getNick ( ) ) , f . attr ( "data-jid" , c . getJid ( ) ) , f . children ( "div.label" ) . text ( c . getNick ( ) ) , f . attr ( "id" , "user-" + a + "-" + Candy . Util . jidToId ( c . getJid ( ) ) ) } } , a } ( Candy . View . Pane || { } , jQuery ) , Candy . View . Pane = function ( a ) { return a . Window = { _hasFocus : ! 0 , _plainTitle : window . top . document . title , _unreadMessagesCount : 0 , autoscroll : ! 0 , hasFocus : function ( ) { return a . Window . _hasFocus } , increaseUnreadMessages : function ( ) { a . Window . renderUnreadMessages ( ++ a . Windo
banActionLabel : "Banir" , youHaveBeenBannedBy : "Você foi banido de %1$s por %2$s" , youHaveBeenBanned : "Você foi banido de %s" , privateActionLabel : "Conversa privada" , ignoreActionLabel : "Ignorar" , unignoreActionLabel : "Não ignorar" , setSubjectActionLabel : "Mudar Assunto" , administratorMessageSubject : "Administrador" , userJoinedRoom : "%s entrou na sala." , userLeftRoom : "%s saiu da sala." , userHasBeenKickedFromRoom : "%s foi derrubado da sala." , userHasBeenBannedFromRoom : "%s foi banido da sala." , dateFormat : "dd.mm.yyyy" , timeFormat : "HH:MM:ss" , tooltipRole : "Moderador" , tooltipIgnored : "Você ignora este usuário" , tooltipEmoticons : "Emoticons" , tooltipSound : "Tocar som para novas mensagens privadas" , tooltipAutoscroll : "Auto-rolagem" , tooltipStatusmessage : "Exibir mensagens de estados" , tooltipAdministration : "Administração de Sala" , tooltipUsercount : "Participantes da Sala" , enterRoomPassword : 'Sala "%s" é protegida por senha.' , enterRoomPasswordSubmit : "Entrar na sala" , passwordEnteredInvalid : 'Senha inváida para sala "%s".' , nicknameConflict : "Nome de usuário já em uso. Por favor escolha outro." , errorMembersOnly : 'Você não pode entrar na sala "%s": privilégios insuficientes.' , errorMaxOccupantsReached : 'Você não pode entrar na sala "%s": máximo de participantes atingido.' , antiSpamMessage : "Por favor, não faça spam. Você foi bloqueado temporariamente." } , ru : { status : "Статус: %s" , statusConnecting : "Подключение..." , statusConnected : "Подключено" , statusDisconnecting : "Отключение..." , statusDisconnected : "Отключено" , statusAuthfail : "Неверный логин" , roomSubject : "Топик:" , messageSubmit : "Послать" , labelUsername : "Имя:" , labelNickname : "Ник:" , labelPassword : "Пароль:" , loginSubmit : "Логин" , loginInvalid : "Неверный JID" , reason : "Причина:" , subject : "Топик:" , reasonWas : "Причина была: %s." , kickActionLabel : "Выбросить" , youHaveBeenKickedBy : "Пользователь %1$s выбросил вас из чата %2$s" , youHaveBeenKicked : "В а с выбросили из чата %s" , banActionLabel : "Запретить доступ" , youHaveBeenBannedBy : "Пользователь %1$s запретил вам доступ в чат %2$s" , youHaveBeenBanned : "Вам запретили доступ в чат %s" , privateActionLabel : "Один-на-один чат" , ignoreActionLabel : "Игнорировать" , unignoreActionLabel : "Отменить игнорирование" , setSubjectActionLabel : "Изменить топик" , administratorMessageSubject : "Администратор" , userJoinedRoom : "%s вошёл в чат." , userLeftRoom : "%s вышел из чата." , userHasBeenKickedFromRoom : "%s выброшен из чата." , userHasBeenBannedFromRoom : "%s запрещён доступ в чат." , userChangedNick : "%1$s сменил имя на %2$s." , presenceUnknownWarningSubject : "Уведомление:" , presenceUnknownWarning : "Этот пользователь вероятнее всего оффлайн." , dateFormat : "dd.mm.yyyy" , timeFormat : "HH:MM:ss" , tooltipRole : "Модератор" , tooltipIgnored : "Вы игнорируете этого пользователя." , tooltipEmoticons : "Смайлики" , tooltipSound : "Озвучивать новое частное сообщение" , tooltipAutoscroll : "Авто-прокручивание" , tooltipStatusmessage : "Показывать статус сообщения" , tooltipAdministration : "Администрирование чат комнаты" , tooltipUsercount : "Участники чата" , enterRoomPassword : 'Чат комната "%s" защищена паролем.' , enterRoomPasswordSubmit : "Войти в чат" , passwordEnteredInvalid : 'Неверный пароль для комнаты "%s".' , nicknameConflict : "Это имя уже используется. Пожалуйста выберите другое имя." , errorMembersOnly : 'Вы не можете войти в чат "%s": Недостаточно прав доступа.' , errorMaxOccupantsReached : ' Вы не можете войти в чат "%s" : Слишком много уч <EFBFBD>
2015-02-20 03:45:47 +01:00
//# sourceMappingURL=candy.min.map