quick_frontend: use of new logging system
This commit is contained in:
parent
233d4b4268
commit
468206e529
5 changed files with 62 additions and 58 deletions
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
from sat.core.i18n import _
|
||||
import sys
|
||||
from logging import debug, info, warning, error
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from sat.tools.jid import JID
|
||||
from sat_frontends.bridge.DBus import DBusBridgeFrontend
|
||||
from sat.core.exceptions import BridgeExceptionNoService, BridgeInitError
|
||||
|
|
@ -96,7 +97,7 @@ class QuickApp(object):
|
|||
"""Must be called after initialization is done, do all automatic task (auto plug profile)"""
|
||||
if self.options.profile:
|
||||
if not self.bridge.getProfileName(self.options.profile):
|
||||
error(_("Trying to plug an unknown profile (%s)" % self.options.profile))
|
||||
log.error(_("Trying to plug an unknown profile (%s)" % self.options.profile))
|
||||
else:
|
||||
self.plug_profile(self.options.profile)
|
||||
|
||||
|
|
@ -117,19 +118,19 @@ class QuickApp(object):
|
|||
return args
|
||||
|
||||
def _getParamError(self, ignore):
|
||||
error(_("Can't get profile parameter"))
|
||||
log.error(_("Can't get profile parameter"))
|
||||
|
||||
def plug_profile(self, profile_key='@DEFAULT@'):
|
||||
"""Tell application which profile must be used"""
|
||||
if self.single_profile and self.profiles:
|
||||
error(_('There is already one profile plugged (we are in single profile mode) !'))
|
||||
log.error(_('There is already one profile plugged (we are in single profile mode) !'))
|
||||
return
|
||||
profile = self.bridge.getProfileName(profile_key)
|
||||
if not profile:
|
||||
error(_("The profile asked doesn't exist"))
|
||||
log.error(_("The profile asked doesn't exist"))
|
||||
return
|
||||
if profile in self.profiles:
|
||||
warning(_("The profile is already plugged"))
|
||||
log.warning(_("The profile is already plugged"))
|
||||
return
|
||||
self.profiles[profile] = {}
|
||||
if self.single_profile:
|
||||
|
|
@ -151,7 +152,7 @@ class QuickApp(object):
|
|||
def plug_profile_4(self, watched, autoconnect, profile):
|
||||
if autoconnect and not self.bridge.isConnected(profile):
|
||||
#Does the user want autoconnection ?
|
||||
self.bridge.asyncConnect(profile, callback=lambda: self.plug_profile_5(watched, autoconnect, profile), errback=lambda ignore: error(_('Error during autoconnection')))
|
||||
self.bridge.asyncConnect(profile, callback=lambda: self.plug_profile_5(watched, autoconnect, profile), errback=lambda ignore: log.error(_('Error during autoconnection')))
|
||||
else:
|
||||
self.plug_profile_5(watched, autoconnect, profile)
|
||||
|
||||
|
|
@ -203,7 +204,7 @@ class QuickApp(object):
|
|||
def unplug_profile(self, profile):
|
||||
"""Tell the application to not follow anymore the profile"""
|
||||
if not profile in self.profiles:
|
||||
warning(_("This profile is not plugged"))
|
||||
log.warning(_("This profile is not plugged"))
|
||||
return
|
||||
self.profiles.remove(profile)
|
||||
|
||||
|
|
@ -214,14 +215,14 @@ class QuickApp(object):
|
|||
"""called when the connection is made"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Connected"))
|
||||
log.debug(_("Connected"))
|
||||
self.setStatusOnline(True)
|
||||
|
||||
def disconnected(self, profile):
|
||||
"""called when the connection is closed"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Disconnected"))
|
||||
log.debug(_("Disconnected"))
|
||||
self.contact_list.clearContacts()
|
||||
self.setStatusOnline(False)
|
||||
|
||||
|
|
@ -229,12 +230,12 @@ class QuickApp(object):
|
|||
"""called when something goes wrong with the connection"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Connection Error"))
|
||||
log.debug(_("Connection Error"))
|
||||
self.disconnected(profile)
|
||||
if error_type == "AUTH_ERROR":
|
||||
self.showDialog(_("Can't connect to account, please check your password"), _("Connection error"), "error")
|
||||
else:
|
||||
error(_('FIXME: error_type %s not implemented') % error_type)
|
||||
log.error(_('FIXME: error_type %s not implemented') % error_type)
|
||||
|
||||
def newContact(self, JabberId, attributes, groups, profile):
|
||||
if not self.check_profile(profile):
|
||||
|
|
@ -302,7 +303,7 @@ class QuickApp(object):
|
|||
if not self.check_profile(profile):
|
||||
return
|
||||
|
||||
debug(_("presence update for %(jid)s (show=%(show)s, priority=%(priority)s, statuses=%(statuses)s) [profile:%(profile)s]")
|
||||
log.debug(_("presence update for %(jid)s (show=%(show)s, priority=%(priority)s, statuses=%(statuses)s) [profile:%(profile)s]")
|
||||
% {'jid': jabber_id, 'show': show, 'priority': priority, 'statuses': statuses, 'profile': profile})
|
||||
from_jid = JID(jabber_id)
|
||||
|
||||
|
|
@ -351,7 +352,7 @@ class QuickApp(object):
|
|||
"""Called when a MUC room is joined"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Room [%(room_jid)s] joined by %(profile)s, users presents:%(users)s") % {'room_jid': room_jid, 'profile': profile, 'users': room_nicks})
|
||||
log.debug(_("Room [%(room_jid)s] joined by %(profile)s, users presents:%(users)s") % {'room_jid': room_jid, 'profile': profile, 'users': room_nicks})
|
||||
self.chat_wins[room_jid].setUserNick(user_nick)
|
||||
self.chat_wins[room_jid].setType("group")
|
||||
self.chat_wins[room_jid].id = room_jid
|
||||
|
|
@ -362,7 +363,7 @@ class QuickApp(object):
|
|||
"""Called when a MUC room is left"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Room [%(room_jid)s] left by %(profile)s") % {'room_jid': room_jid_s, 'profile': profile})
|
||||
log.debug(_("Room [%(room_jid)s] left by %(profile)s") % {'room_jid': room_jid_s, 'profile': profile})
|
||||
del self.chat_wins[room_jid_s]
|
||||
self.contact_list.remove(JID(room_jid_s))
|
||||
|
||||
|
|
@ -372,7 +373,7 @@ class QuickApp(object):
|
|||
return
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].replaceUser(user_nick)
|
||||
debug(_("user [%(user_nick)s] joined room [%(room_jid)s]") % {'user_nick': user_nick, 'room_jid': room_jid})
|
||||
log.debug(_("user [%(user_nick)s] joined room [%(room_jid)s]") % {'user_nick': user_nick, 'room_jid': room_jid})
|
||||
|
||||
def roomUserLeft(self, room_jid, user_nick, user_data, profile):
|
||||
"""Called when an user joined a MUC room"""
|
||||
|
|
@ -380,7 +381,7 @@ class QuickApp(object):
|
|||
return
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].removeUser(user_nick)
|
||||
debug(_("user [%(user_nick)s] left room [%(room_jid)s]") % {'user_nick': user_nick, 'room_jid': room_jid})
|
||||
log.debug(_("user [%(user_nick)s] left room [%(room_jid)s]") % {'user_nick': user_nick, 'room_jid': room_jid})
|
||||
|
||||
def roomUserChangedNick(self, room_jid, old_nick, new_nick, profile):
|
||||
"""Called when an user joined a MUC room"""
|
||||
|
|
@ -388,7 +389,7 @@ class QuickApp(object):
|
|||
return
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].changeUserNick(old_nick, new_nick)
|
||||
debug(_("user [%(old_nick)s] is now known as [%(new_nick)s] in room [%(room_jid)s]") % {'old_nick': old_nick, 'new_nick': new_nick, 'room_jid': room_jid})
|
||||
log.debug(_("user [%(old_nick)s] is now known as [%(new_nick)s] in room [%(room_jid)s]") % {'old_nick': old_nick, 'new_nick': new_nick, 'room_jid': room_jid})
|
||||
|
||||
def roomNewSubject(self, room_jid, subject, profile):
|
||||
"""Called when subject of MUC room change"""
|
||||
|
|
@ -396,20 +397,20 @@ class QuickApp(object):
|
|||
return
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].setSubject(subject)
|
||||
debug(_("new subject for room [%(room_jid)s]: %(subject)s") % {'room_jid': room_jid, "subject": subject})
|
||||
log.debug(_("new subject for room [%(room_jid)s]: %(subject)s") % {'room_jid': room_jid, "subject": subject})
|
||||
|
||||
def tarotGameStarted(self, room_jid, referee, players, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Tarot Game Started \o/"))
|
||||
log.debug(_("Tarot Game Started \o/"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].startGame("Tarot", referee, players)
|
||||
debug(_("new Tarot game started by [%(referee)s] in room [%(room_jid)s] with %(players)s") % {'referee': referee, 'room_jid': room_jid, 'players': [str(player) for player in players]})
|
||||
log.debug(_("new Tarot game started by [%(referee)s] in room [%(room_jid)s] with %(players)s") % {'referee': referee, 'room_jid': room_jid, 'players': [str(player) for player in players]})
|
||||
|
||||
def tarotGameNew(self, room_jid, hand, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("New Tarot Game"))
|
||||
log.debug(_("New Tarot Game"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Tarot").newGame(hand)
|
||||
|
||||
|
|
@ -417,21 +418,21 @@ class QuickApp(object):
|
|||
"""Called when the player has to select his contrat"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Tarot: need to select a contrat"))
|
||||
log.debug(_("Tarot: need to select a contrat"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Tarot").chooseContrat(xml_data)
|
||||
|
||||
def tarotShowCards(self, room_jid, game_stage, cards, data, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Show cards"))
|
||||
log.debug(_("Show cards"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Tarot").showCards(game_stage, cards, data)
|
||||
|
||||
def tarotMyTurn(self, room_jid, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("My turn to play"))
|
||||
log.debug(_("My turn to play"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Tarot").myTurn()
|
||||
|
||||
|
|
@ -439,36 +440,36 @@ class QuickApp(object):
|
|||
"""Called when the game is finished and the score are updated"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Tarot: score received"))
|
||||
log.debug(_("Tarot: score received"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Tarot").showScores(xml_data, winners, loosers)
|
||||
|
||||
def tarotCardsPlayed(self, room_jid, player, cards, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Card(s) played (%(player)s): %(cards)s") % {"player": player, "cards": cards})
|
||||
log.debug(_("Card(s) played (%(player)s): %(cards)s") % {"player": player, "cards": cards})
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Tarot").cardsPlayed(player, cards)
|
||||
|
||||
def tarotInvalidCards(self, room_jid, phase, played_cards, invalid_cards, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Cards played are not valid: %s") % invalid_cards)
|
||||
log.debug(_("Cards played are not valid: %s") % invalid_cards)
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Tarot").invalidCards(phase, played_cards, invalid_cards)
|
||||
|
||||
def quizGameStarted(self, room_jid, referee, players, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("Quiz Game Started \o/"))
|
||||
log.debug(_("Quiz Game Started \o/"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].startGame("Quiz", referee, players)
|
||||
debug(_("new Quiz game started by [%(referee)s] in room [%(room_jid)s] with %(players)s") % {'referee': referee, 'room_jid': room_jid, 'players': [str(player) for player in players]})
|
||||
log.debug(_("new Quiz game started by [%(referee)s] in room [%(room_jid)s] with %(players)s") % {'referee': referee, 'room_jid': room_jid, 'players': [str(player) for player in players]})
|
||||
|
||||
def quizGameNew(self, room_jid, data, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("New Quiz Game"))
|
||||
log.debug(_("New Quiz Game"))
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Quiz").quizGameNew(data)
|
||||
|
||||
|
|
@ -476,7 +477,7 @@ class QuickApp(object):
|
|||
"""Called when a new question is asked"""
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_(u"Quiz: new question: %s") % question)
|
||||
log.debug(_(u"Quiz: new question: %s") % question)
|
||||
if room_jid in self.chat_wins:
|
||||
self.chat_wins[room_jid].getGame("Quiz").quizGameQuestion(question_id, question, timer)
|
||||
|
||||
|
|
@ -571,9 +572,9 @@ class QuickApp(object):
|
|||
def paramUpdate(self, name, value, namespace, profile):
|
||||
if not self.check_profile(profile):
|
||||
return
|
||||
debug(_("param update: [%(namespace)s] %(name)s = %(value)s") % {'namespace': namespace, 'name': name, 'value': value})
|
||||
log.debug(_("param update: [%(namespace)s] %(name)s = %(value)s") % {'namespace': namespace, 'name': name, 'value': value})
|
||||
if (namespace, name) == ("Connection", "JabberID"):
|
||||
debug(_("Changing JID to %s"), value)
|
||||
log.debug(_("Changing JID to %s") % value)
|
||||
self.profiles[profile]['whoami'] = JID(value)
|
||||
elif (namespace, name) == ("Misc", "Watched"):
|
||||
self.profiles[profile]['watched'] = value.split()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from logging import debug, info, error
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from sat.tools.jid import JID
|
||||
|
||||
|
||||
|
|
@ -153,7 +154,7 @@ class QuickCardGame(object):
|
|||
elif phase == "ecart":
|
||||
self.state = "ecart"
|
||||
else:
|
||||
error ('INTERNAL ERROR: unmanaged game phase')
|
||||
log.error ('INTERNAL ERROR: unmanaged game phase')
|
||||
|
||||
for suit, value in played_cards:
|
||||
self.hand.append(self.cards[suit, value])
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from sat.core.i18n import _
|
||||
from logging import debug, info, warning, error
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from sat.tools.jid import JID
|
||||
from sat_frontends.quick_frontend.quick_utils import unescapePrivate
|
||||
from sat_frontends.quick_frontend.constants import Const
|
||||
|
|
@ -44,17 +45,17 @@ class QuickChat(object):
|
|||
"""Set the users presents in the contact list for a group chat
|
||||
@param nicks: list of nicknames
|
||||
"""
|
||||
debug (_("Adding users %s to room") % nicks)
|
||||
log.debug (_("Adding users %s to room") % nicks)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to set presents nicks for a non group chat window"))
|
||||
log.error (_("[INTERNAL] trying to set presents nicks for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
self.occupants.update(nicks)
|
||||
|
||||
def replaceUser(self, nick, show_info=True):
|
||||
"""Add user if it is not in the group list"""
|
||||
debug (_("Replacing user %s") % nick)
|
||||
log.debug (_("Replacing user %s") % nick)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to replace user for a non group chat window"))
|
||||
log.error (_("[INTERNAL] trying to replace user for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
len_before = len(self.occupants)
|
||||
self.occupants.add(nick)
|
||||
|
|
@ -63,9 +64,9 @@ class QuickChat(object):
|
|||
|
||||
def removeUser(self, nick, show_info=True):
|
||||
"""Remove a user from the group list"""
|
||||
debug(_("Removing user %s") % nick)
|
||||
log.debug(_("Removing user %s") % nick)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to remove user for a non group chat window"))
|
||||
log.error (_("[INTERNAL] trying to remove user for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
self.occupants.remove(nick)
|
||||
if show_info:
|
||||
|
|
@ -80,9 +81,9 @@ class QuickChat(object):
|
|||
|
||||
def changeUserNick(self, old_nick, new_nick):
|
||||
"""Change nick of a user in group list"""
|
||||
debug(_("Changing nick of user %(old_nick)s to %(new_nick)s") % {"old_nick": old_nick, "new_nick": new_nick})
|
||||
log.debug(_("Changing nick of user %(old_nick)s to %(new_nick)s") % {"old_nick": old_nick, "new_nick": new_nick})
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to change user nick for a non group chat window"))
|
||||
log.error (_("[INTERNAL] trying to change user nick for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
self.removeUser(old_nick, show_info=False)
|
||||
self.replaceUser(new_nick, show_info=False)
|
||||
|
|
@ -90,14 +91,14 @@ class QuickChat(object):
|
|||
|
||||
def setSubject(self, subject):
|
||||
"""Set title for a group chat"""
|
||||
debug(_("Setting subject to %s") % subject)
|
||||
log.debug(_("Setting subject to %s") % subject)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to set subject for a non group chat window"))
|
||||
log.error (_("[INTERNAL] trying to set subject for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
|
||||
def historyPrint(self, size=20, profile='@NONE@'):
|
||||
"""Print the initial history"""
|
||||
debug (_("now we print history"))
|
||||
log.debug (_("now we print history"))
|
||||
def onHistory(history):
|
||||
for line in history:
|
||||
timestamp, from_jid, to_jid, message, _type, extra = line
|
||||
|
|
@ -107,7 +108,7 @@ class QuickChat(object):
|
|||
self.printMessage(JID(from_jid), message, profile, timestamp)
|
||||
|
||||
def onHistoryError(err):
|
||||
error (_("Can't get history"))
|
||||
log.error (_("Can't get history"))
|
||||
|
||||
if self.target.startswith(Const.PRIVATE_PREFIX):
|
||||
target = unescapePrivate(self.target)
|
||||
|
|
@ -146,12 +147,12 @@ class QuickChat(object):
|
|||
def startGame(self, game_type, referee, players):
|
||||
"""Configure the chat window to start a game"""
|
||||
#No need to raise an error as game are not mandatory
|
||||
warning(_('startGame is not implemented in this frontend'))
|
||||
log.warning(_('startGame is not implemented in this frontend'))
|
||||
|
||||
def getGame(self, game_type):
|
||||
"""Return class managing the game type"""
|
||||
#No need to raise an error as game are not mandatory
|
||||
warning(_('getGame is not implemented in this frontend'))
|
||||
log.warning(_('getGame is not implemented in this frontend'))
|
||||
|
||||
def updateChatState(self, state, nick=None):
|
||||
"""Set the chat state (XEP-0085) of the contact. Leave nick to None
|
||||
|
|
|
|||
|
|
@ -18,14 +18,15 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from sat.core.i18n import _
|
||||
from logging import debug
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
|
||||
|
||||
class QuickContactList(object):
|
||||
"""This class manage the visual representation of contacts"""
|
||||
|
||||
def __init__(self):
|
||||
debug(_("Contact List init"))
|
||||
log.debug(_("Contact List init"))
|
||||
self._cache = {}
|
||||
self.specials={}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from sat.core.i18n import _
|
||||
from logging import debug, info, warning, error
|
||||
from sat.core.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
from sat.tools.jid import JID
|
||||
import pdb
|
||||
|
||||
|
||||
class QuickContactManagement(object):
|
||||
|
|
@ -68,7 +68,7 @@ class QuickContactManagement(object):
|
|||
if self.__contactlist[entity.bare].has_key(name):
|
||||
return self.__contactlist[entity.bare][name]
|
||||
else:
|
||||
debug(_('Trying to get attribute for an unknown contact'))
|
||||
log.debug(_('Trying to get attribute for an unknown contact'))
|
||||
return None
|
||||
|
||||
def isConnected(self, entity):
|
||||
|
|
@ -84,7 +84,7 @@ class QuickContactManagement(object):
|
|||
#no more resource available: the contact seems really disconnected
|
||||
del self.__contactlist[entity.bare]
|
||||
except KeyError:
|
||||
error(_('INTERNAL ERROR: Key error'))
|
||||
log.error(_('INTERNAL ERROR: Key log.error'))
|
||||
raise
|
||||
|
||||
def update(self, entity, key, value):
|
||||
|
|
@ -96,7 +96,7 @@ class QuickContactManagement(object):
|
|||
if self.__contactlist.has_key(entity.bare):
|
||||
self.__contactlist[entity.bare][key] = value
|
||||
else:
|
||||
debug (_('Trying to update an unknown contact: %s'), entity.bare)
|
||||
log.debug (_('Trying to update an unknown contact: %s') % entity.bare)
|
||||
|
||||
def get_full(self, entity):
|
||||
return entity.bare+'/'+self.__contactlist[entity.bare]['resources'][-1]
|
||||
|
|
|
|||
Loading…
Reference in a new issue