2009-11-23 15:08:09 +01:00
|
|
|
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
|
2009-09-12 15:51:21 +02:00
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
"""
|
2009-10-02 22:57:11 +02:00
|
|
|
Provides an actual implementation for the standard commands.
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
|
|
|
|
2009-11-19 06:39:04 +01:00
|
|
|
from time import localtime, strftime
|
|
|
|
from datetime import date
|
|
|
|
|
2009-09-13 16:43:44 +02:00
|
|
|
import dialogs
|
2009-09-12 15:51:21 +02:00
|
|
|
from common import gajim
|
2009-09-13 16:43:44 +02:00
|
|
|
from common import helpers
|
|
|
|
from common.exceptions import GajimGeneralException
|
2009-11-19 06:39:04 +01:00
|
|
|
from common.logger import Constants
|
2009-09-12 15:51:21 +02:00
|
|
|
|
2009-11-01 13:50:34 +01:00
|
|
|
from ..errors import CommandError
|
2009-10-04 19:43:51 +02:00
|
|
|
from ..framework import CommandContainer, command, documentation
|
2009-10-02 22:57:11 +02:00
|
|
|
from ..mapping import generate_usage
|
2009-09-12 15:51:21 +02:00
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
from hosts import ChatCommands, PrivateChatCommands, GroupChatCommands
|
|
|
|
|
2009-11-19 06:39:04 +01:00
|
|
|
# This holds constants fron the logger, which we'll be using in some of our
|
|
|
|
# commands.
|
|
|
|
lc = Constants()
|
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
class StandardCommonCommands(CommandContainer):
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
2009-10-02 22:57:11 +02:00
|
|
|
This command container contains standard commands which are common to all -
|
|
|
|
chat, private chat, group chat.
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
HOSTS = (ChatCommands, PrivateChatCommands, GroupChatCommands)
|
|
|
|
|
2009-09-12 15:51:21 +02:00
|
|
|
@command
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Clear the text window"))
|
2009-09-12 15:51:21 +02:00
|
|
|
def clear(self):
|
|
|
|
self.conv_textview.clear()
|
|
|
|
|
|
|
|
@command
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Hide the chat buttons"))
|
2009-09-12 15:51:21 +02:00
|
|
|
def compact(self):
|
2009-10-02 22:57:11 +02:00
|
|
|
new_status = not self.hide_chat_buttons
|
|
|
|
self.chat_buttons_set_visible(new_status)
|
2009-09-12 15:51:21 +02:00
|
|
|
|
2009-09-17 03:38:39 +02:00
|
|
|
@command(overlap=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Show help on a given command or a list of available commands if -(-a)ll is given"))
|
2009-09-12 15:51:21 +02:00
|
|
|
def help(self, command=None, all=False):
|
|
|
|
if command:
|
2009-10-02 22:57:11 +02:00
|
|
|
command = self.get_command(command)
|
|
|
|
|
|
|
|
documentation = _(command.extract_documentation())
|
|
|
|
usage = generate_usage(command)
|
|
|
|
|
2009-10-04 18:56:07 +02:00
|
|
|
text = []
|
2009-10-02 22:57:11 +02:00
|
|
|
|
|
|
|
if documentation:
|
2009-10-04 18:56:07 +02:00
|
|
|
text.append(documentation)
|
2009-10-02 22:57:11 +02:00
|
|
|
if command.usage:
|
2009-10-04 18:56:07 +02:00
|
|
|
text.append(usage)
|
2009-09-12 15:51:21 +02:00
|
|
|
|
2009-10-04 18:56:07 +02:00
|
|
|
return '\n\n'.join(text)
|
2009-09-12 15:51:21 +02:00
|
|
|
elif all:
|
|
|
|
for command in self.list_commands():
|
|
|
|
names = ', '.join(command.names)
|
|
|
|
description = command.extract_description()
|
|
|
|
|
|
|
|
self.echo("%s - %s" % (names, description))
|
|
|
|
else:
|
2009-10-02 22:57:11 +02:00
|
|
|
help = self.get_command('help')
|
|
|
|
self.echo(help(self, 'help'))
|
2009-09-12 15:51:21 +02:00
|
|
|
|
|
|
|
@command(raw=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Send a message to the contact"))
|
2009-09-12 15:51:21 +02:00
|
|
|
def say(self, message):
|
|
|
|
self.send(message)
|
|
|
|
|
|
|
|
@command(raw=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Send action (in the third person) to the current chat"))
|
2009-09-12 15:51:21 +02:00
|
|
|
def me(self, action):
|
|
|
|
self.send("/me %s" % action)
|
|
|
|
|
2009-11-19 06:39:04 +01:00
|
|
|
@command('lastlog', overlap=True)
|
|
|
|
@documentation(_("Show logged messages which mention given text"))
|
|
|
|
def grep(self, text, limit=None):
|
|
|
|
results = gajim.logger.get_search_results_for_query(self.contact.jid,
|
|
|
|
text, self.account)
|
|
|
|
|
|
|
|
if not results:
|
|
|
|
raise CommandError(_("%s: Nothing found") % text)
|
|
|
|
|
|
|
|
if limit:
|
|
|
|
try:
|
|
|
|
results = results[len(results) - int(limit):]
|
|
|
|
except ValueError:
|
|
|
|
raise CommandError(_("Limit must be an integer"))
|
|
|
|
|
|
|
|
for row in results:
|
|
|
|
contact, time, kind, show, message, subject = row
|
|
|
|
|
|
|
|
if not contact:
|
|
|
|
if kind == lc.KIND_CHAT_MSG_SENT:
|
|
|
|
contact = gajim.nicks[self.account]
|
|
|
|
else:
|
|
|
|
contact = self.contact.name
|
|
|
|
|
|
|
|
time_obj = localtime(time)
|
|
|
|
date_obj = date.fromtimestamp(time)
|
|
|
|
date_ = strftime('%Y-%m-%d', time_obj)
|
|
|
|
time_ = strftime('%H:%M:%S', time_obj)
|
|
|
|
|
|
|
|
if date_obj == date.today():
|
|
|
|
formatted = "[%s] %s: %s" % (time_, contact, message)
|
|
|
|
else:
|
|
|
|
formatted = "[%s, %s] %s: %s" % (date_, time_, contact, message)
|
|
|
|
|
|
|
|
self.echo(formatted)
|
|
|
|
|
2009-12-22 20:31:11 +01:00
|
|
|
@command(raw=True, empty=True)
|
|
|
|
@documentation(_("""
|
|
|
|
Set current the status
|
|
|
|
|
|
|
|
Status can be given as one of the following values: online, away,
|
|
|
|
chat, xa, dnd.
|
|
|
|
"""))
|
|
|
|
def status(self, status, message):
|
|
|
|
if status not in ('online', 'away', 'chat', 'xa', 'dnd'):
|
|
|
|
raise CommandError("Invalid status given")
|
|
|
|
for connection in gajim.connections.itervalues():
|
|
|
|
connection.change_status(status, message)
|
|
|
|
|
|
|
|
@command(raw=True, empty=True)
|
|
|
|
@documentation(_("Set the current status to away"))
|
|
|
|
def away(self, message):
|
|
|
|
if not message:
|
|
|
|
message = _("Away")
|
|
|
|
for connection in gajim.connections.itervalues():
|
|
|
|
connection.change_status('away', message)
|
|
|
|
|
|
|
|
@command('back', raw=True, empty=True)
|
|
|
|
@documentation(_("Set the current status to online"))
|
|
|
|
def online(self, message):
|
|
|
|
if not message:
|
|
|
|
message = _("Available")
|
|
|
|
for connection in gajim.connections.itervalues():
|
|
|
|
connection.change_status('online', message)
|
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
class StandardChatCommands(CommandContainer):
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
2009-10-02 22:57:11 +02:00
|
|
|
This command container contains standard command which are unique to a chat.
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
HOSTS = (ChatCommands,)
|
2009-09-12 15:51:21 +02:00
|
|
|
|
|
|
|
@command
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Send a ping to the contact"))
|
2009-09-12 15:51:21 +02:00
|
|
|
def ping(self):
|
|
|
|
if self.account == gajim.ZEROCONF_ACC_NAME:
|
2009-09-12 22:22:50 +02:00
|
|
|
raise CommandError(_('Command is not supported for zeroconf accounts'))
|
2009-09-12 15:51:21 +02:00
|
|
|
gajim.connections[self.account].sendPing(self.contact)
|
|
|
|
|
2010-01-10 07:42:08 +01:00
|
|
|
@command
|
2009-11-13 22:58:02 +01:00
|
|
|
@documentation(_("Sends DTMF events through an open audio session"))
|
|
|
|
def dtmf(self, events):
|
|
|
|
if not self.audio_sid:
|
|
|
|
raise CommandError(_("There is no open audio session with this contact"))
|
|
|
|
# Valid values for DTMF tones are *, # or a number
|
|
|
|
events = [event for event in events
|
|
|
|
if event in ('*', '#') or event.isdigit()]
|
|
|
|
if events:
|
|
|
|
session = gajim.connections[self.account].get_jingle_session(
|
|
|
|
self.contact.get_full_jid(), self.audio_sid)
|
|
|
|
content = session.get_content('audio')
|
|
|
|
content.batch_dtmf(events)
|
|
|
|
else:
|
|
|
|
raise CommandError(_("No valid DTMF event specified"))
|
|
|
|
|
2010-01-10 07:42:08 +01:00
|
|
|
@command
|
2009-11-10 22:06:59 +01:00
|
|
|
@documentation(_("Toggle audio session"))
|
|
|
|
def audio(self):
|
|
|
|
if self.audio_state == self.JINGLE_STATE_NOT_AVAILABLE:
|
|
|
|
raise CommandError(_("Video sessions are not available"))
|
|
|
|
else:
|
2009-11-10 22:33:39 +01:00
|
|
|
# A state of an audio session is toggled by inverting a state of the
|
|
|
|
# appropriate button.
|
|
|
|
state = self._audio_button.get_active()
|
|
|
|
self._audio_button.set_active(not state)
|
2009-11-10 22:06:59 +01:00
|
|
|
|
2010-01-10 07:42:08 +01:00
|
|
|
@command
|
2009-11-10 22:06:59 +01:00
|
|
|
@documentation(_("Toggle video session"))
|
|
|
|
def video(self):
|
|
|
|
if self.video_state == self.JINGLE_STATE_NOT_AVAILABLE:
|
|
|
|
raise CommandError(_("Video sessions are not available"))
|
|
|
|
else:
|
2009-11-10 22:33:39 +01:00
|
|
|
# A state of a video session is toggled by inverting a state of the
|
|
|
|
# appropriate button.
|
|
|
|
state = self._video_button.get_active()
|
|
|
|
self._video_button.set_active(not state)
|
2009-11-10 22:06:59 +01:00
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
class StandardPrivateChatCommands(CommandContainer):
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
2009-10-02 22:57:11 +02:00
|
|
|
This command container contains standard command which are unique to a
|
|
|
|
private chat.
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
HOSTS = (PrivateChatCommands,)
|
2009-09-12 15:51:21 +02:00
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
class StandardGroupchatCommands(CommandContainer):
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
2009-10-02 22:57:11 +02:00
|
|
|
This command container contains standard command which are unique to a group
|
|
|
|
chat.
|
2009-09-12 15:51:21 +02:00
|
|
|
"""
|
|
|
|
|
2009-10-02 22:57:11 +02:00
|
|
|
HOSTS = (GroupChatCommands,)
|
2009-09-13 16:43:44 +02:00
|
|
|
|
|
|
|
@command(raw=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Change your nickname in a group chat"))
|
2009-09-13 16:43:44 +02:00
|
|
|
def nick(self, new_nick):
|
|
|
|
try:
|
|
|
|
new_nick = helpers.parse_resource(new_nick)
|
|
|
|
except Exception:
|
|
|
|
raise CommandError(_("Invalid nickname"))
|
|
|
|
self.connection.join_gc(new_nick, self.room_jid, None, change_nick=True)
|
2009-09-15 21:59:48 +02:00
|
|
|
self.new_nick = new_nick
|
2009-09-13 16:43:44 +02:00
|
|
|
|
|
|
|
@command('query', raw=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Open a private chat window with a specified occupant"))
|
2009-09-13 16:43:44 +02:00
|
|
|
def chat(self, nick):
|
|
|
|
nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
|
|
|
|
if nick in nicks:
|
|
|
|
self.on_send_pm(nick=nick)
|
|
|
|
else:
|
|
|
|
raise CommandError(_("Nickname not found"))
|
|
|
|
|
2009-09-17 03:38:39 +02:00
|
|
|
@command('msg', raw=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Open a private chat window with a specified occupant and send him a message"))
|
2009-09-17 03:38:39 +02:00
|
|
|
def message(self, nick, a_message):
|
2009-09-13 16:43:44 +02:00
|
|
|
nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
|
|
|
|
if nick in nicks:
|
|
|
|
self.on_send_pm(nick=nick, msg=a_message)
|
|
|
|
else:
|
|
|
|
raise CommandError(_("Nickname not found"))
|
|
|
|
|
|
|
|
@command(raw=True, empty=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Display or change a group chat topic"))
|
2009-09-13 16:43:44 +02:00
|
|
|
def topic(self, new_topic):
|
|
|
|
if new_topic:
|
|
|
|
self.connection.send_gc_subject(self.room_jid, new_topic)
|
|
|
|
else:
|
|
|
|
return self.subject
|
|
|
|
|
2009-09-17 03:38:39 +02:00
|
|
|
@command(raw=True, empty=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Invite a user to a room for a reason"))
|
2009-09-17 03:38:39 +02:00
|
|
|
def invite(self, jid, reason):
|
2009-09-13 16:43:44 +02:00
|
|
|
self.connection.send_invite(self.room_jid, jid, reason)
|
|
|
|
return _("Invited %s to %s") % (jid, self.room_jid)
|
|
|
|
|
2009-09-17 03:38:39 +02:00
|
|
|
@command(raw=True, empty=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Join a group chat given by a jid, optionally using given nickname"))
|
2009-09-17 03:38:39 +02:00
|
|
|
def join(self, jid, nick):
|
|
|
|
if not nick:
|
|
|
|
nick = self.nick
|
2009-09-13 16:43:44 +02:00
|
|
|
|
|
|
|
if '@' not in jid:
|
|
|
|
jid = jid + '@' + gajim.get_server_from_jid(self.room_jid)
|
|
|
|
|
|
|
|
try:
|
|
|
|
gajim.interface.instances[self.account]['join_gc'].window.present()
|
|
|
|
except KeyError:
|
|
|
|
try:
|
2009-10-28 15:43:05 +01:00
|
|
|
dialogs.JoinGroupchatWindow(account=self.account, room_jid=jid, nick=nick)
|
2009-09-13 16:43:44 +02:00
|
|
|
except GajimGeneralException:
|
|
|
|
pass
|
|
|
|
|
|
|
|
@command('part', 'close', raw=True, empty=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Leave the groupchat, optionally giving a reason, and close tab or window"))
|
2009-09-13 16:43:44 +02:00
|
|
|
def leave(self, reason):
|
|
|
|
self.parent_win.remove_tab(self, self.parent_win.CLOSE_COMMAND, reason)
|
|
|
|
|
2009-10-05 11:55:34 +02:00
|
|
|
@command(raw=True, empty=True)
|
2009-10-04 19:43:51 +02:00
|
|
|
@documentation(_("""
|
|
|
|
Ban user by a nick or a jid from a groupchat
|
|
|
|
|
|
|
|
If given nickname is not found it will be treated as a jid.
|
|
|
|
"""))
|
2009-09-17 03:38:39 +02:00
|
|
|
def ban(self, who, reason):
|
2009-09-13 16:43:44 +02:00
|
|
|
if who in gajim.contacts.get_nick_list(self.account, self.room_jid):
|
|
|
|
contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, who)
|
|
|
|
who = contact.jid
|
2009-09-17 03:38:39 +02:00
|
|
|
self.connection.gc_set_affiliation(self.room_jid, who, 'outcast', reason or str())
|
2009-09-13 16:43:44 +02:00
|
|
|
|
2009-09-17 03:38:39 +02:00
|
|
|
@command(raw=True, empty=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Kick user by a nick from a groupchat"))
|
2009-09-17 03:38:39 +02:00
|
|
|
def kick(self, who, reason):
|
2009-09-13 16:43:44 +02:00
|
|
|
if not who in gajim.contacts.get_nick_list(self.account, self.room_jid):
|
|
|
|
raise CommandError(_("Nickname not found"))
|
2009-09-17 03:38:39 +02:00
|
|
|
self.connection.gc_set_role(self.room_jid, who, 'none', reason or str())
|
2009-09-13 16:43:44 +02:00
|
|
|
|
|
|
|
@command
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Display names of all group chat occupants"))
|
2009-09-13 16:43:44 +02:00
|
|
|
def names(self, verbose=False):
|
|
|
|
get_contact = lambda nick: gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
|
|
|
|
nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
|
|
|
|
|
|
|
|
# First we do alpha-numeric sort and then role-based one.
|
|
|
|
nicks.sort()
|
|
|
|
nicks.sort(key=lambda nick: get_contact(nick).role)
|
|
|
|
|
|
|
|
if verbose:
|
|
|
|
for nick in nicks:
|
|
|
|
contact = get_contact(nick)
|
|
|
|
|
|
|
|
role = helpers.get_uf_role(contact.role)
|
|
|
|
affiliation = helpers.get_uf_affiliation(contact.affiliation)
|
|
|
|
|
|
|
|
self.echo("%s - %s - %s" % (nick, role, affiliation))
|
|
|
|
else:
|
|
|
|
return ', '.join(nicks)
|
|
|
|
|
2009-10-04 21:11:19 +02:00
|
|
|
@command('ignore', raw=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Forbid an occupant to send you public or private messages"))
|
2009-09-13 16:43:44 +02:00
|
|
|
def block(self, who):
|
|
|
|
self.on_block(None, who)
|
|
|
|
|
2009-10-04 21:11:19 +02:00
|
|
|
@command('unignore', raw=True)
|
2009-10-05 11:55:34 +02:00
|
|
|
@documentation(_("Allow an occupant to send you public or private messages"))
|
2009-09-13 16:43:44 +02:00
|
|
|
def unblock(self, who):
|
|
|
|
self.on_unblock(None, who)
|