Subversion Repositories navi

Compare Revisions

Regard whitespace Rev 248 → Rev 48

/GPL
File deleted
/LICENCE
File deleted
/ircbot/ircbot.py
File deleted
/ircbot/README.txt
File deleted
/ircbot/bot.py
File deleted
Property changes:
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Index: ircbot/irclib.py
===================================================================
--- ircbot/irclib.py (revision 248)
+++ ircbot/irclib.py (nonexistent)
@@ -1,1557 +0,0 @@
-# Copyright (C) 1999--2002 Joel Rosdahl
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# keltus
-#
-# $Id: irclib.py,v 1.47 2008/09/25 22:00:59 keltus Exp $
-import bisect
-import re
-import select
-import socket
-import string
-import time
-import types
-
-"""irclib -- Internet Relay Chat (IRC) protocol client library.
-
-This library is intended to encapsulate the IRC protocol at a quite
-low level. It provides an event-driven IRC client framework. It has
-a fairly thorough support for the basic IRC protocol, CTCP, DCC chat,
-but DCC file transfers is not yet supported.
-
-In order to understand how to make an IRC client, I'm afraid you more
-or less must understand the IRC specifications. They are available
-here: [IRC specifications].
-
-The main features of the IRC client framework are:
-
- * Abstraction of the IRC protocol.
- * Handles multiple simultaneous IRC server connections.
- * Handles server PONGing transparently.
- * Messages to the IRC server are done by calling methods on an IRC
- connection object.
- * Messages from an IRC server triggers events, which can be caught
- by event handlers.
- * Reading from and writing to IRC server sockets are normally done
- by an internal select() loop, but the select()ing may be done by
- an external main loop.
- * Functions can be registered to execute at specified times by the
- event-loop.
- * Decodes CTCP tagging correctly (hopefully); I haven't seen any
- other IRC client implementation that handles the CTCP
- specification subtilties.
- * A kind of simple, single-server, object-oriented IRC client class
- that dispatches events to instance methods is included.
-
-Current limitations:
-
- * The IRC protocol shines through the abstraction a bit too much.
- * Data is not written asynchronously to the server, i.e. the write()
- may block if the TCP buffers are stuffed.
- * There are no support for DCC file transfers.
- * The author haven't even read RFC 2810, 2811, 2812 and 2813.
- * Like most projects, documentation is lacking...
-
-.. [IRC specifications] http://www.irchelp.org/irchelp/rfc/
-"""
-
-
-VERSION = 0, 4, 8
-DEBUG = 0
-
-# TODO
-# ----
-# (maybe) thread safety
-# (maybe) color parser convenience functions
-# documentation (including all event types)
-# (maybe) add awareness of different types of ircds
-# send data asynchronously to the server (and DCC connections)
-# (maybe) automatically close unused, passive DCC connections after a while
-
-# NOTES
-# -----
-# connection.quit() only sends QUIT to the server.
-# ERROR from the server triggers the error event and the disconnect event.
-# dropping of the connection triggers the disconnect event.
-
-class IRCError(Exception):
- """Represents an IRC exception."""
- pass
-
-
-class IRC:
- """Class that handles one or several IRC server connections.
-
- When an IRC object has been instantiated, it can be used to create
- Connection objects that represent the IRC connections. The
- responsibility of the IRC object is to provide an event-driven
- framework for the connections and to keep the connections alive.
- It runs a select loop to poll each connection's TCP socket and
- hands over the sockets with incoming data for processing by the
- corresponding connection.
-
- The methods of most interest for an IRC client writer are server,
- add_global_handler, remove_global_handler, execute_at,
- execute_delayed, process_once and process_forever.
-
- Here is an example:
-
- irc = irclib.IRC()
- server = irc.server()
- server.connect(\"irc.some.where\", 6667, \"my_nickname\")
- server.privmsg(\"a_nickname\", \"Hi there!\")
- irc.process_forever()
-
- This will connect to the IRC server irc.some.where on port 6667
- using the nickname my_nickname and send the message \"Hi there!\"
- to the nickname a_nickname.
- """
-
- def __init__(self, fn_to_add_socket=None,
- fn_to_remove_socket=None,
- fn_to_add_timeout=None):
- """Constructor for IRC objects.
-
- Optional arguments are fn_to_add_socket, fn_to_remove_socket
- and fn_to_add_timeout. The first two specify functions that
- will be called with a socket object as argument when the IRC
- object wants to be notified (or stop being notified) of data
- coming on a new socket. When new data arrives, the method
- process_data should be called. Similarly, fn_to_add_timeout
- is called with a number of seconds (a floating point number)
- as first argument when the IRC object wants to receive a
- notification (by calling the process_timeout method). So, if
- e.g. the argument is 42.17, the object wants the
- process_timeout method to be called after 42 seconds and 170
- milliseconds.
-
- The three arguments mainly exist to be able to use an external
- main loop (for example Tkinter's or PyGTK's main app loop)
- instead of calling the process_forever method.
-
- An alternative is to just call ServerConnection.process_once()
- once in a while.
- """
-
- if fn_to_add_socket and fn_to_remove_socket:
- self.fn_to_add_socket = fn_to_add_socket
- self.fn_to_remove_socket = fn_to_remove_socket
- else:
- self.fn_to_add_socket = None
- self.fn_to_remove_socket = None
-
- self.fn_to_add_timeout = fn_to_add_timeout
- self.connections = []
- self.handlers = {}
- self.delayed_commands = [] # list of tuples in the format (time, function, arguments)
-
- self.add_global_handler("ping", _ping_ponger, -42)
-
- def server(self):
- """Creates and returns a ServerConnection object."""
-
- c = ServerConnection(self)
- self.connections.append(c)
- return c
-
- def process_data(self, sockets):
- """Called when there is more data to read on connection sockets.
-
- Arguments:
-
- sockets -- A list of socket objects.
-
- See documentation for IRC.__init__.
- """
- for s in sockets:
- for c in self.connections:
- if s == c._get_socket():
- c.process_data()
-
- def process_timeout(self):
- """Called when a timeout notification is due.
-
- See documentation for IRC.__init__.
- """
- t = time.time()
- while self.delayed_commands:
- if t >= self.delayed_commands[0][0]:
- self.delayed_commands[0][1](*self.delayed_commands[0][2])
- del self.delayed_commands[0]
- else:
- break
-
- def process_once(self, timeout=0):
- """Process data from connections once.
-
- Arguments:
-
- timeout -- How long the select() call should wait if no
- data is available.
-
- This method should be called periodically to check and process
- incoming data, if there are any. If that seems boring, look
- at the process_forever method.
- """
- sockets = map(lambda x: x._get_socket(), self.connections)
- sockets = filter(lambda x: x != None, sockets)
- if sockets:
- (i, o, e) = select.select(sockets, [], [], timeout)
- self.process_data(i)
- else:
- time.sleep(timeout)
- self.process_timeout()
-
- def process_forever(self, timeout=0.2):
- """Run an infinite loop, processing data from connections.
-
- This method repeatedly calls process_once.
-
- Arguments:
-
- timeout -- Parameter to pass to process_once.
- """
- while 1:
- self.process_once(timeout)
-
- def disconnect_all(self, message=""):
- """Disconnects all connections."""
- for c in self.connections:
- c.disconnect(message)
-
- def add_global_handler(self, event, handler, priority=0):
- """Adds a global handler function for a specific event type.
-
- Arguments:
-
- event -- Event type (a string). Check the values of the
- numeric_events dictionary in irclib.py for possible event
- types.
-
- handler -- Callback function.
-
- priority -- A number (the lower number, the higher priority).
-
- The handler function is called whenever the specified event is
- triggered in any of the connections. See documentation for
- the Event class.
-
- The handler functions are called in priority order (lowest
- number is highest priority). If a handler function returns
- \"NO MORE\", no more handlers will be called.
- """
- if not event in self.handlers:
- self.handlers[event] = []
- bisect.insort(self.handlers[event], ((priority, handler)))
-
- def remove_global_handler(self, event, handler):
- """Removes a global handler function.
-
- Arguments:
-
- event -- Event type (a string).
-
- handler -- Callback function.
-
- Returns 1 on success, otherwise 0.
- """
- if not event in self.handlers:
- return 0
- for h in self.handlers[event]:
- if handler == h[1]:
- self.handlers[event].remove(h)
- return 1
-
- def execute_at(self, at, function, arguments=()):
- """Execute a function at a specified time.
-
- Arguments:
-
- at -- Execute at this time (standard \"time_t\" time).
-
- function -- Function to call.
-
- arguments -- Arguments to give the function.
- """
- self.execute_delayed(at - time.time(), function, arguments)
-
- def execute_delayed(self, delay, function, arguments=()):
- """Execute a function after a specified time.
-
- Arguments:
-
- delay -- How many seconds to wait.
-
- function -- Function to call.
-
- arguments -- Arguments to give the function.
- """
- bisect.insort(self.delayed_commands, (delay + time.time(), function, arguments))
- if self.fn_to_add_timeout:
- self.fn_to_add_timeout(delay)
-
- def dcc(self, dcctype="chat"):
- """Creates and returns a DCCConnection object.
-
- Arguments:
-
- dcctype -- "chat" for DCC CHAT connections or "raw" for
- DCC SEND (or other DCC types). If "chat",
- incoming data will be split in newline-separated
- chunks. If "raw", incoming data is not touched.
- """
- c = DCCConnection(self, dcctype)
- self.connections.append(c)
- return c
-
- def _handle_event(self, connection, event):
- """[Internal]"""
- h = self.handlers
- for handler in h.get("all_events", []) + h.get(event.eventtype(), []):
- if handler[1](connection, event) == "NO MORE":
- return
-
- def _remove_connection(self, connection):
- """[Internal]"""
- self.connections.remove(connection)
- if self.fn_to_remove_socket:
- self.fn_to_remove_socket(connection._get_socket())
-
-_rfc_1459_command_regexp = re.compile("^(:(?P[^ ]+) +)?(?P[^ ]+)( *(?P .+))?")
-
-class Connection:
- """Base class for IRC connections.
-
- Must be overridden.
- """
- def __init__(self, irclibobj):
- self.irclibobj = irclibobj
-
- def _get_socket(self):
- raise IRCError, "Not overridden"
-
- ##############################
- ### Convenience wrappers.
-
- def execute_at(self, at, function, arguments=()):
- self.irclibobj.execute_at(at, function, arguments)
-
- def execute_delayed(self, delay, function, arguments=()):
- self.irclibobj.execute_delayed(delay, function, arguments)
-
-
-class ServerConnectionError(IRCError):
- pass
-
-class ServerNotConnectedError(ServerConnectionError):
- pass
-
-
-# Huh!? Crrrrazy EFNet doesn't follow the RFC: their ircd seems to
-# use \n as message separator! :P
-_linesep_regexp = re.compile("\r?\n")
-
-class ServerConnection(Connection):
- """This class represents an IRC server connection.
-
- ServerConnection objects are instantiated by calling the server
- method on an IRC object.
- """
-
- def __init__(self, irclibobj):
- Connection.__init__(self, irclibobj)
- self.connected = 0 # Not connected yet.
- self.socket = None
- self.ssl = None
-
- def connect(self, server, port, nickname, password=None, username=None,
- ircname=None, localaddress="", localport=0, ssl=False, ipv6=False):
- """Connect/reconnect to a server.
-
- Arguments:
-
- server -- Server name.
-
- port -- Port number.
-
- nickname -- The nickname.
-
- password -- Password (if any).
-
- username -- The username.
-
- ircname -- The IRC name ("realname").
-
- localaddress -- Bind the connection to a specific local IP address.
-
- localport -- Bind the connection to a specific local port.
-
- ssl -- Enable support for ssl.
-
- ipv6 -- Enable support for ipv6.
-
- This function can be called to reconnect a closed connection.
-
- Returns the ServerConnection object.
- """
- if self.connected:
- self.disconnect("Changing servers")
-
- self.previous_buffer = ""
- self.handlers = {}
- self.real_server_name = ""
- self.real_nickname = nickname
- self.server = server
- self.port = port
- self.nickname = nickname
- self.username = username or nickname
- self.ircname = ircname or nickname
- self.password = password
- self.localaddress = localaddress
- self.localport = localport
- self.localhost = socket.gethostname()
- if ipv6:
- self.socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
- else:
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- try:
- self.socket.bind((self.localaddress, self.localport))
- self.socket.connect((self.server, self.port))
- if ssl:
- self.ssl = socket.ssl(self.socket)
- except socket.error, x:
- self.socket.close()
- self.socket = None
- raise ServerConnectionError, "Couldn't connect to socket: %s" % x
- self.connected = 1
- if self.irclibobj.fn_to_add_socket:
- self.irclibobj.fn_to_add_socket(self.socket)
-
- # Log on...
- if self.password:
- self.pass_(self.password)
- self.nick(self.nickname)
- self.user(self.username, self.ircname)
- return self
-
- def close(self):
- """Close the connection.
-
- This method closes the connection permanently; after it has
- been called, the object is unusable.
- """
-
- self.disconnect("Closing object")
- self.irclibobj._remove_connection(self)
-
- def _get_socket(self):
- """[Internal]"""
- return self.socket
-
- def get_server_name(self):
- """Get the (real) server name.
-
- This method returns the (real) server name, or, more
- specifically, what the server calls itself.
- """
-
- if self.real_server_name:
- return self.real_server_name
- else:
- return ""
-
- def get_nickname(self):
- """Get the (real) nick name.
-
- This method returns the (real) nickname. The library keeps
- track of nick changes, so it might not be the nick name that
- was passed to the connect() method. """
-
- return self.real_nickname
-
- def process_data(self):
- """[Internal]"""
-
- try:
- if self.ssl:
- new_data = self.ssl.read(2 ** 14)
- else:
- new_data = self.socket.recv(2 ** 14)
- except socket.error, x:
- # The server hung up.
- self.disconnect("Connection reset by peer")
- return
- if not new_data:
- # Read nothing: connection must be down.
- self.disconnect("Connection reset by peer")
- return
-
- lines = _linesep_regexp.split(self.previous_buffer + new_data)
-
- # Save the last, unfinished line.
- self.previous_buffer = lines.pop()
-
- for line in lines:
- if DEBUG:
- print "FROM SERVER:", line
-
- if not line:
- continue
-
- prefix = None
- command = None
- arguments = None
- self._handle_event(Event("all_raw_messages",
- self.get_server_name(),
- None,
- [line]))
-
- m = _rfc_1459_command_regexp.match(line)
- if m.group("prefix"):
- prefix = m.group("prefix")
- if not self.real_server_name:
- self.real_server_name = prefix
-
- if m.group("command"):
- command = m.group("command").lower()
-
- if m.group("argument"):
- a = m.group("argument").split(" :", 1)
- arguments = a[0].split()
- if len(a) == 2:
- arguments.append(a[1])
-
- # Translate numerics into more readable strings.
- if command in numeric_events:
- command = numeric_events[command]
-
- if command == "nick":
- if nm_to_n(prefix) == self.real_nickname:
- self.real_nickname = arguments[0]
- elif command == "welcome":
- # Record the nickname in case the client changed nick
- # in a nicknameinuse callback.
- self.real_nickname = arguments[0]
-
- if command in ["privmsg", "notice"]:
- target, message = arguments[0], arguments[1]
- messages = _ctcp_dequote(message)
-
- if command == "privmsg":
- if is_channel(target):
- command = "pubmsg"
- else:
- if is_channel(target):
- command = "pubnotice"
- else:
- command = "privnotice"
-
- for m in messages:
- if type(m) is types.TupleType:
- if command in ["privmsg", "pubmsg"]:
- command = "ctcp"
- else:
- command = "ctcpreply"
-
- m = list(m)
- if DEBUG:
- print "command: %s, source: %s, target: %s, arguments: %s" % (
- command, prefix, target, m)
- self._handle_event(Event(command, prefix, target, m))
- if command == "ctcp" and m[0] == "ACTION":
- self._handle_event(Event("action", prefix, target, m[1:]))
- else:
- if DEBUG:
- print "command: %s, source: %s, target: %s, arguments: %s" % (
- command, prefix, target, [m])
- self._handle_event(Event(command, prefix, target, [m]))
- else:
- target = None
-
- if command == "quit":
- arguments = [arguments[0]]
- elif command == "ping":
- target = arguments[0]
- else:
- target = arguments[0]
- arguments = arguments[1:]
-
- if command == "mode":
- if not is_channel(target):
- command = "umode"
-
- if DEBUG:
- print "command: %s, source: %s, target: %s, arguments: %s" % (
- command, prefix, target, arguments)
- self._handle_event(Event(command, prefix, target, arguments))
-
- def _handle_event(self, event):
- """[Internal]"""
- self.irclibobj._handle_event(self, event)
- if event.eventtype() in self.handlers:
- for fn in self.handlers[event.eventtype()]:
- fn(self, event)
-
- def is_connected(self):
- """Return connection status.
-
- Returns true if connected, otherwise false.
- """
- return self.connected
-
- def add_global_handler(self, *args):
- """Add global handler.
-
- See documentation for IRC.add_global_handler.
- """
- self.irclibobj.add_global_handler(*args)
-
- def remove_global_handler(self, *args):
- """Remove global handler.
-
- See documentation for IRC.remove_global_handler.
- """
- self.irclibobj.remove_global_handler(*args)
-
- def action(self, target, action):
- """Send a CTCP ACTION command."""
- self.ctcp("ACTION", target, action)
-
- def admin(self, server=""):
- """Send an ADMIN command."""
- self.send_raw(" ".join(["ADMIN", server]).strip())
-
- def ctcp(self, ctcptype, target, parameter=""):
- """Send a CTCP command."""
- ctcptype = ctcptype.upper()
- self.privmsg(target, "\001%s%s\001" % (ctcptype, parameter and (" " + parameter) or ""))
-
- def ctcp_reply(self, target, parameter):
- """Send a CTCP REPLY command."""
- self.notice(target, "\001%s\001" % parameter)
-
- def disconnect(self, message=""):
- """Hang up the connection.
-
- Arguments:
-
- message -- Quit message.
- """
- if not self.connected:
- return
-
- self.connected = 0
-
- self.quit(message)
-
- try:
- self.socket.close()
- except socket.error, x:
- pass
- self.socket = None
- self._handle_event(Event("disconnect", self.server, "", [message]))
-
- def globops(self, text):
- """Send a GLOBOPS command."""
- self.send_raw("GLOBOPS :" + text)
-
- def info(self, server=""):
- """Send an INFO command."""
- self.send_raw(" ".join(["INFO", server]).strip())
-
- def invite(self, nick, channel):
- """Send an INVITE command."""
- self.send_raw(" ".join(["INVITE", nick, channel]).strip())
-
- def ison(self, nicks):
- """Send an ISON command.
-
- Arguments:
-
- nicks -- List of nicks.
- """
- self.send_raw("ISON " + " ".join(nicks))
-
- def join(self, channel, key=""):
- """Send a JOIN command."""
- self.send_raw("JOIN %s%s" % (channel, (key and (" " + key))))
-
- def kick(self, channel, nick, comment=""):
- """Send a KICK command."""
- self.send_raw("KICK %s %s%s" % (channel, nick, (comment and (" :" + comment))))
-
- def links(self, remote_server="", server_mask=""):
- """Send a LINKS command."""
- command = "LINKS"
- if remote_server:
- command = command + " " + remote_server
- if server_mask:
- command = command + " " + server_mask
- self.send_raw(command)
-
- def list(self, channels=None, server=""):
- """Send a LIST command."""
- command = "LIST"
- if channels:
- command = command + " " + ",".join(channels)
- if server:
- command = command + " " + server
- self.send_raw(command)
-
- def lusers(self, server=""):
- """Send a LUSERS command."""
- self.send_raw("LUSERS" + (server and (" " + server)))
-
- def mode(self, target, command):
- """Send a MODE command."""
- self.send_raw("MODE %s %s" % (target, command))
-
- def motd(self, server=""):
- """Send an MOTD command."""
- self.send_raw("MOTD" + (server and (" " + server)))
-
- def names(self, channels=None):
- """Send a NAMES command."""
- self.send_raw("NAMES" + (channels and (" " + ",".join(channels)) or ""))
-
- def nick(self, newnick):
- """Send a NICK command."""
- self.send_raw("NICK " + newnick)
-
- def notice(self, target, text):
- """Send a NOTICE command."""
- # Should limit len(text) here!
- self.send_raw("NOTICE %s :%s" % (target, text))
-
- def oper(self, nick, password):
- """Send an OPER command."""
- self.send_raw("OPER %s %s" % (nick, password))
-
- def part(self, channels, message=""):
- """Send a PART command."""
- if type(channels) == types.StringType:
- self.send_raw("PART " + channels + (message and (" " + message)))
- else:
- self.send_raw("PART " + ",".join(channels) + (message and (" " + message)))
-
- def pass_(self, password):
- """Send a PASS command."""
- self.send_raw("PASS " + password)
-
- def ping(self, target, target2=""):
- """Send a PING command."""
- self.send_raw("PING %s%s" % (target, target2 and (" " + target2)))
-
- def pong(self, target, target2=""):
- """Send a PONG command."""
- self.send_raw("PONG %s%s" % (target, target2 and (" " + target2)))
-
- def privmsg(self, target, text):
- """Send a PRIVMSG command."""
- # Should limit len(text) here!
- self.send_raw("PRIVMSG %s :%s" % (target, text))
-
- def privmsg_many(self, targets, text):
- """Send a PRIVMSG command to multiple targets."""
- # Should limit len(text) here!
- self.send_raw("PRIVMSG %s :%s" % (",".join(targets), text))
-
- def quit(self, message=""):
- """Send a QUIT command."""
- # Note that many IRC servers don't use your QUIT message
- # unless you've been connected for at least 5 minutes!
- self.send_raw("QUIT" + (message and (" :" + message)))
-
- def send_raw(self, string):
- """Send raw string to the server.
-
- The string will be padded with appropriate CR LF.
- """
- if self.socket is None:
- raise ServerNotConnectedError, "Not connected."
- try:
- if self.ssl:
- self.ssl.write(string + "\r\n")
- else:
- self.socket.send(string + "\r\n")
- if DEBUG:
- print "TO SERVER:", string
- except socket.error, x:
- # Ouch!
- self.disconnect("Connection reset by peer.")
-
- def squit(self, server, comment=""):
- """Send an SQUIT command."""
- self.send_raw("SQUIT %s%s" % (server, comment and (" :" + comment)))
-
- def stats(self, statstype, server=""):
- """Send a STATS command."""
- self.send_raw("STATS %s%s" % (statstype, server and (" " + server)))
-
- def time(self, server=""):
- """Send a TIME command."""
- self.send_raw("TIME" + (server and (" " + server)))
-
- def topic(self, channel, new_topic=None):
- """Send a TOPIC command."""
- if new_topic is None:
- self.send_raw("TOPIC " + channel)
- else:
- self.send_raw("TOPIC %s :%s" % (channel, new_topic))
-
- def trace(self, target=""):
- """Send a TRACE command."""
- self.send_raw("TRACE" + (target and (" " + target)))
-
- def user(self, username, realname):
- """Send a USER command."""
- self.send_raw("USER %s 0 * :%s" % (username, realname))
-
- def userhost(self, nicks):
- """Send a USERHOST command."""
- self.send_raw("USERHOST " + ",".join(nicks))
-
- def users(self, server=""):
- """Send a USERS command."""
- self.send_raw("USERS" + (server and (" " + server)))
-
- def version(self, server=""):
- """Send a VERSION command."""
- self.send_raw("VERSION" + (server and (" " + server)))
-
- def wallops(self, text):
- """Send a WALLOPS command."""
- self.send_raw("WALLOPS :" + text)
-
- def who(self, target="", op=""):
- """Send a WHO command."""
- self.send_raw("WHO%s%s" % (target and (" " + target), op and (" o")))
-
- def whois(self, targets):
- """Send a WHOIS command."""
- self.send_raw("WHOIS " + ",".join(targets))
-
- def whowas(self, nick, maxx="", server=""):
- """Send a WHOWAS command."""
- self.send_raw("WHOWAS %s%s%s" % (nick,
- maxx and (" " + maxx),
- server and (" " + server)))
-
-class DCCConnectionError(IRCError):
- pass
-
-
-class DCCConnection(Connection):
- """This class represents a DCC connection.
-
- DCCConnection objects are instantiated by calling the dcc
- method on an IRC object.
- """
- def __init__(self, irclibobj, dcctype):
- Connection.__init__(self, irclibobj)
- self.connected = 0
- self.passive = 0
- self.dcctype = dcctype
- self.peeraddress = None
- self.peerport = None
-
- def connect(self, address, port):
- """Connect/reconnect to a DCC peer.
-
- Arguments:
- address -- Host/IP address of the peer.
-
- port -- The port number to connect to.
-
- Returns the DCCConnection object.
- """
- self.peeraddress = socket.gethostbyname(address)
- self.peerport = port
- self.socket = None
- self.previous_buffer = ""
- self.handlers = {}
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.passive = 0
- try:
- self.socket.connect((self.peeraddress, self.peerport))
- except socket.error, x:
- raise DCCConnectionError, "Couldn't connect to socket: %s" % x
- self.connected = 1
- if self.irclibobj.fn_to_add_socket:
- self.irclibobj.fn_to_add_socket(self.socket)
- return self
-
- def listen(self):
- """Wait for a connection/reconnection from a DCC peer.
-
- Returns the DCCConnection object.
-
- The local IP address and port are available as
- self.localaddress and self.localport. After connection from a
- peer, the peer address and port are available as
- self.peeraddress and self.peerport.
- """
- self.previous_buffer = ""
- self.handlers = {}
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.passive = 1
- try:
- self.socket.bind((socket.gethostbyname(socket.gethostname()), 0))
- self.localaddress, self.localport = self.socket.getsockname()
- self.socket.listen(10)
- except socket.error, x:
- raise DCCConnectionError, "Couldn't bind socket: %s" % x
- return self
-
- def disconnect(self, message=""):
- """Hang up the connection and close the object.
-
- Arguments:
-
- message -- Quit message.
- """
- if not self.connected:
- return
-
- self.connected = 0
- try:
- self.socket.close()
- except socket.error, x:
- pass
- self.socket = None
- self.irclibobj._handle_event(
- self,
- Event("dcc_disconnect", self.peeraddress, "", [message]))
- self.irclibobj._remove_connection(self)
-
- def process_data(self):
- """[Internal]"""
-
- if self.passive and not self.connected:
- conn, (self.peeraddress, self.peerport) = self.socket.accept()
- self.socket.close()
- self.socket = conn
- self.connected = 1
- if DEBUG:
- print "DCC connection from %s:%d" % (
- self.peeraddress, self.peerport)
- self.irclibobj._handle_event(
- self,
- Event("dcc_connect", self.peeraddress, None, None))
- return
-
- try:
- new_data = self.socket.recv(2 ** 14)
- except socket.error, x:
- # The server hung up.
- self.disconnect("Connection reset by peer")
- return
- if not new_data:
- # Read nothing: connection must be down.
- self.disconnect("Connection reset by peer")
- return
-
- if self.dcctype == "chat":
- # The specification says lines are terminated with LF, but
- # it seems safer to handle CR LF terminations too.
- chunks = _linesep_regexp.split(self.previous_buffer + new_data)
-
- # Save the last, unfinished line.
- self.previous_buffer = chunks[-1]
- if len(self.previous_buffer) > 2 ** 14:
- # Bad peer! Naughty peer!
- self.disconnect()
- return
- chunks = chunks[:-1]
- else:
- chunks = [new_data]
-
- command = "dccmsg"
- prefix = self.peeraddress
- target = None
- for chunk in chunks:
- if DEBUG:
- print "FROM PEER:", chunk
- arguments = [chunk]
- if DEBUG:
- print "command: %s, source: %s, target: %s, arguments: %s" % (
- command, prefix, target, arguments)
- self.irclibobj._handle_event(
- self,
- Event(command, prefix, target, arguments))
-
- def _get_socket(self):
- """[Internal]"""
- return self.socket
-
- def privmsg(self, string):
- """Send data to DCC peer.
-
- The string will be padded with appropriate LF if it's a DCC
- CHAT session.
- """
- try:
- self.socket.send(string)
- if self.dcctype == "chat":
- self.socket.send("\n")
- if DEBUG:
- print "TO PEER: %s\n" % string
- except socket.error, x:
- # Ouch!
- self.disconnect("Connection reset by peer.")
-
-class SimpleIRCClient:
- """A simple single-server IRC client class.
-
- This is an example of an object-oriented wrapper of the IRC
- framework. A real IRC client can be made by subclassing this
- class and adding appropriate methods.
-
- The method on_join will be called when a "join" event is created
- (which is done when the server sends a JOIN messsage/command),
- on_privmsg will be called for "privmsg" events, and so on. The
- handler methods get two arguments: the connection object (same as
- self.connection) and the event object.
-
- Instance attributes that can be used by sub classes:
-
- ircobj -- The IRC instance.
-
- connection -- The ServerConnection instance.
-
- dcc_connections -- A list of DCCConnection instances.
- """
- def __init__(self):
- self.ircobj = IRC()
- self.connection = self.ircobj.server()
- self.dcc_connections = []
- self.ircobj.add_global_handler("all_events", self._dispatcher, -10)
- self.ircobj.add_global_handler("dcc_disconnect", self._dcc_disconnect, -10)
-
- def _dispatcher(self, c, e):
- """[Internal]"""
- m = "on_" + e.eventtype()
- if hasattr(self, m):
- getattr(self, m)(c, e)
-
- def _dcc_disconnect(self, c, e):
- self.dcc_connections.remove(c)
-
- def connect(self, server, port, nickname, password=None, username=None,
- ircname=None, localaddress="", localport=0, ssl=False, ipv6=False):
- """Connect/reconnect to a server.
-
- Arguments:
-
- server -- Server name.
-
- port -- Port number.
-
- nickname -- The nickname.
-
- password -- Password (if any).
-
- username -- The username.
-
- ircname -- The IRC name.
-
- localaddress -- Bind the connection to a specific local IP address.
-
- localport -- Bind the connection to a specific local port.
-
- ssl -- Enable support for ssl.
-
- ipv6 -- Enable support for ipv6.
-
- This function can be called to reconnect a closed connection.
- """
- self.connection.connect(server, port, nickname,
- password, username, ircname,
- localaddress, localport, ssl, ipv6)
-
- def dcc_connect(self, address, port, dcctype="chat"):
- """Connect to a DCC peer.
-
- Arguments:
-
- address -- IP address of the peer.
-
- port -- Port to connect to.
-
- Returns a DCCConnection instance.
- """
- dcc = self.ircobj.dcc(dcctype)
- self.dcc_connections.append(dcc)
- dcc.connect(address, port)
- return dcc
-
- def dcc_listen(self, dcctype="chat"):
- """Listen for connections from a DCC peer.
-
- Returns a DCCConnection instance.
- """
- dcc = self.ircobj.dcc(dcctype)
- self.dcc_connections.append(dcc)
- dcc.listen()
- return dcc
-
- def start(self):
- """Start the IRC client."""
- self.ircobj.process_forever()
-
-
-class Event:
- """Class representing an IRC event."""
- def __init__(self, eventtype, source, target, arguments=None):
- """Constructor of Event objects.
-
- Arguments:
-
- eventtype -- A string describing the event.
-
- source -- The originator of the event (a nick mask or a server).
-
- target -- The target of the event (a nick or a channel).
-
- arguments -- Any event specific arguments.
- """
- self._eventtype = eventtype
- self._source = source
- self._target = target
- if arguments:
- self._arguments = arguments
- else:
- self._arguments = []
-
- def eventtype(self):
- """Get the event type."""
- return self._eventtype
-
- def source(self):
- """Get the event source."""
- return self._source
-
- def target(self):
- """Get the event target."""
- return self._target
-
- def arguments(self):
- """Get the event arguments."""
- return self._arguments
-
-_LOW_LEVEL_QUOTE = "\020"
-_CTCP_LEVEL_QUOTE = "\134"
-_CTCP_DELIMITER = "\001"
-
-_low_level_mapping = {
- "0": "\000",
- "n": "\n",
- "r": "\r",
- _LOW_LEVEL_QUOTE: _LOW_LEVEL_QUOTE
-}
-
-_low_level_regexp = re.compile(_LOW_LEVEL_QUOTE + "(.)")
-
-def mask_matches(nick, mask):
- """Check if a nick matches a mask.
-
- Returns true if the nick matches, otherwise false.
- """
- nick = irc_lower(nick)
- mask = irc_lower(mask)
- mask = mask.replace("\\", "\\\\")
- for ch in ".$|[](){}+":
- mask = mask.replace(ch, "\\" + ch)
- mask = mask.replace("?", ".")
- mask = mask.replace("*", ".*")
- r = re.compile(mask, re.IGNORECASE)
- return r.match(nick)
-
-_special = "-[]\\`^{}"
-nick_characters = string.ascii_letters + string.digits + _special
-_ircstring_translation = string.maketrans(string.ascii_uppercase + "[]\\^",
- string.ascii_lowercase + "{}|~")
-
-def irc_lower(s):
- """Returns a lowercased string.
-
- The definition of lowercased comes from the IRC specification (RFC
- 1459).
- """
- return s.translate(_ircstring_translation)
-
-def _ctcp_dequote(message):
- """[Internal] Dequote a message according to CTCP specifications.
-
- The function returns a list where each element can be either a
- string (normal message) or a tuple of one or two strings (tagged
- messages). If a tuple has only one element (ie is a singleton),
- that element is the tag; otherwise the tuple has two elements: the
- tag and the data.
-
- Arguments:
-
- message -- The message to be decoded.
- """
-
- def _low_level_replace(match_obj):
- ch = match_obj.group(1)
-
- # If low_level_mapping doesn't have the character as key, we
- # should just return the character.
- return _low_level_mapping.get(ch, ch)
-
- if _LOW_LEVEL_QUOTE in message:
- # Yup, there was a quote. Release the dequoter, man!
- message = _low_level_regexp.sub(_low_level_replace, message)
-
- if _CTCP_DELIMITER not in message:
- return [message]
- else:
- # Split it into parts. (Does any IRC client actually *use*
- # CTCP stacking like this?)
- chunks = message.split(_CTCP_DELIMITER)
-
- messages = []
- i = 0
- while i < len(chunks) - 1:
- # Add message if it's non-empty.
- if len(chunks[i]) > 0:
- messages.append(chunks[i])
-
- if i < len(chunks) - 2:
- # Aye! CTCP tagged data ahead!
- messages.append(tuple(chunks[i + 1].split(" ", 1)))
-
- i = i + 2
-
- if len(chunks) % 2 == 0:
- # Hey, a lonely _CTCP_DELIMITER at the end! This means
- # that the last chunk, including the delimiter, is a
- # normal message! (This is according to the CTCP
- # specification.)
- messages.append(_CTCP_DELIMITER + chunks[-1])
-
- return messages
-
-def is_channel(string):
- """Check if a string is a channel name.
-
- Returns true if the argument is a channel name, otherwise false.
- """
- return string and string[0] in "#&+!"
-
-def ip_numstr_to_quad(num):
- """Convert an IP number as an integer given in ASCII
- representation (e.g. '3232235521') to an IP address string
- (e.g. '192.168.0.1')."""
- n = long(num)
- p = map(str, map(int, [n >> 24 & 0xFF, n >> 16 & 0xFF,
- n >> 8 & 0xFF, n & 0xFF]))
- return ".".join(p)
-
-def ip_quad_to_numstr(quad):
- """Convert an IP address string (e.g. '192.168.0.1') to an IP
- number as an integer given in ASCII representation
- (e.g. '3232235521')."""
- p = map(long, quad.split("."))
- s = str((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
- if s[-1] == "L":
- s = s[:-1]
- return s
-
-def nm_to_n(s):
- """Get the nick part of a nickmask.
-
- (The source of an Event is a nickmask.)
- """
- return s.split("!")[0]
-
-def nm_to_uh(s):
- """Get the userhost part of a nickmask.
-
- (The source of an Event is a nickmask.)
- """
- return s.split("!")[1]
-
-def nm_to_h(s):
- """Get the host part of a nickmask.
-
- (The source of an Event is a nickmask.)
- """
- return s.split("@")[1]
-
-def nm_to_u(s):
- """Get the user part of a nickmask.
-
- (The source of an Event is a nickmask.)
- """
- s = s.split("!")[1]
- return s.split("@")[0]
-
-def parse_nick_modes(mode_string):
- """Parse a nick mode string.
-
- The function returns a list of lists with three members: sign,
- mode and argument. The sign is \"+\" or \"-\". The argument is
- always None.
-
- Example:
-
- >>> irclib.parse_nick_modes(\"+ab-c\")
- [['+', 'a', None], ['+', 'b', None], ['-', 'c', None]]
- """
-
- return _parse_modes(mode_string, "")
-
-def parse_channel_modes(mode_string):
- """Parse a channel mode string.
-
- The function returns a list of lists with three members: sign,
- mode and argument. The sign is \"+\" or \"-\". The argument is
- None if mode isn't one of \"b\", \"k\", \"l\", \"v\" or \"o\".
-
- Example:
-
- >>> irclib.parse_channel_modes(\"+ab-c foo\")
- [['+', 'a', None], ['+', 'b', 'foo'], ['-', 'c', None]]
- """
-
- return _parse_modes(mode_string, "bklvo")
-
-def _parse_modes(mode_string, unary_modes=""):
- """[Internal]"""
- modes = []
- arg_count = 0
-
- # State variable.
- sign = ""
-
- a = mode_string.split()
- if len(a) == 0:
- return []
- else:
- mode_part, args = a[0], a[1:]
-
- if mode_part[0] not in "+-":
- return []
- for ch in mode_part:
- if ch in "+-":
- sign = ch
- elif ch in unary_modes:
- if len(args) >= arg_count + 1:
- modes.append([sign, ch, args[arg_count]])
- arg_count = arg_count + 1
- else:
- modes.append([sign, ch, None])
- else:
- modes.append([sign, ch, None])
- return modes
-
-def _ping_ponger(connection, event):
- """[Internal]"""
- connection.pong(event.target())
-
-# Numeric table mostly stolen from the Perl IRC module (Net::IRC).
-numeric_events = {
- "001": "welcome",
- "002": "yourhost",
- "003": "created",
- "004": "myinfo",
- "005": "featurelist", # XXX
- "200": "tracelink",
- "201": "traceconnecting",
- "202": "tracehandshake",
- "203": "traceunknown",
- "204": "traceoperator",
- "205": "traceuser",
- "206": "traceserver",
- "207": "traceservice",
- "208": "tracenewtype",
- "209": "traceclass",
- "210": "tracereconnect",
- "211": "statslinkinfo",
- "212": "statscommands",
- "213": "statscline",
- "214": "statsnline",
- "215": "statsiline",
- "216": "statskline",
- "217": "statsqline",
- "218": "statsyline",
- "219": "endofstats",
- "221": "umodeis",
- "231": "serviceinfo",
- "232": "endofservices",
- "233": "service",
- "234": "servlist",
- "235": "servlistend",
- "241": "statslline",
- "242": "statsuptime",
- "243": "statsoline",
- "244": "statshline",
- "250": "luserconns",
- "251": "luserclient",
- "252": "luserop",
- "253": "luserunknown",
- "254": "luserchannels",
- "255": "luserme",
- "256": "adminme",
- "257": "adminloc1",
- "258": "adminloc2",
- "259": "adminemail",
- "261": "tracelog",
- "262": "endoftrace",
- "263": "tryagain",
- "265": "n_local",
- "266": "n_global",
- "300": "none",
- "301": "away",
- "302": "userhost",
- "303": "ison",
- "305": "unaway",
- "306": "nowaway",
- "311": "whoisuser",
- "312": "whoisserver",
- "313": "whoisoperator",
- "314": "whowasuser",
- "315": "endofwho",
- "316": "whoischanop",
- "317": "whoisidle",
- "318": "endofwhois",
- "319": "whoischannels",
- "321": "liststart",
- "322": "list",
- "323": "listend",
- "324": "channelmodeis",
- "329": "channelcreate",
- "331": "notopic",
- "332": "currenttopic",
- "333": "topicinfo",
- "341": "inviting",
- "342": "summoning",
- "346": "invitelist",
- "347": "endofinvitelist",
- "348": "exceptlist",
- "349": "endofexceptlist",
- "351": "version",
- "352": "whoreply",
- "353": "namreply",
- "361": "killdone",
- "362": "closing",
- "363": "closeend",
- "364": "links",
- "365": "endoflinks",
- "366": "endofnames",
- "367": "banlist",
- "368": "endofbanlist",
- "369": "endofwhowas",
- "371": "info",
- "372": "motd",
- "373": "infostart",
- "374": "endofinfo",
- "375": "motdstart",
- "376": "endofmotd",
- "377": "motd2", # 1997-10-16 -- tkil
- "381": "youreoper",
- "382": "rehashing",
- "384": "myportis",
- "391": "time",
- "392": "usersstart",
- "393": "users",
- "394": "endofusers",
- "395": "nousers",
- "401": "nosuchnick",
- "402": "nosuchserver",
- "403": "nosuchchannel",
- "404": "cannotsendtochan",
- "405": "toomanychannels",
- "406": "wasnosuchnick",
- "407": "toomanytargets",
- "409": "noorigin",
- "411": "norecipient",
- "412": "notexttosend",
- "413": "notoplevel",
- "414": "wildtoplevel",
- "421": "unknowncommand",
- "422": "nomotd",
- "423": "noadmininfo",
- "424": "fileerror",
- "431": "nonicknamegiven",
- "432": "erroneusnickname", # Thiss iz how its speld in thee RFC.
- "433": "nicknameinuse",
- "436": "nickcollision",
- "437": "unavailresource", # "Nick temporally unavailable"
- "441": "usernotinchannel",
- "442": "notonchannel",
- "443": "useronchannel",
- "444": "nologin",
- "445": "summondisabled",
- "446": "usersdisabled",
- "451": "notregistered",
- "461": "needmoreparams",
- "462": "alreadyregistered",
- "463": "nopermforhost",
- "464": "passwdmismatch",
- "465": "yourebannedcreep", # I love this one...
- "466": "youwillbebanned",
- "467": "keyset",
- "471": "channelisfull",
- "472": "unknownmode",
- "473": "inviteonlychan",
- "474": "bannedfromchan",
- "475": "badchannelkey",
- "476": "badchanmask",
- "477": "nochanmodes", # "Channel doesn't support modes"
- "478": "banlistfull",
- "481": "noprivileges",
- "482": "chanoprivsneeded",
- "483": "cantkillserver",
- "484": "restricted", # Connection is restricted
- "485": "uniqopprivsneeded",
- "491": "nooperhost",
- "492": "noservicehost",
- "501": "umodeunknownflag",
- "502": "usersdontmatch",
-}
-
-generated_events = [
- # Generated events
- "dcc_connect",
- "dcc_disconnect",
- "dccmsg",
- "disconnect",
- "ctcp",
- "ctcpreply",
-]
-
-protocol_events = [
- # IRC protocol events
- "error",
- "join",
- "kick",
- "mode",
- "part",
- "ping",
- "privmsg",
- "privnotice",
- "pubmsg",
- "pubnotice",
- "quit",
- "invite",
- "pong",
-]
-
-all_events = generated_events + protocol_events + numeric_events.values()
Index: APACHE_LICENCE
===================================================================
--- APACHE_LICENCE (revision 248)
+++ APACHE_LICENCE (nonexistent)
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
Index: cliapp/tsimapiakcli.py
===================================================================
--- cliapp/tsimapiakcli.py (revision 248)
+++ cliapp/tsimapiakcli.py (nonexistent)
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-# This file is part of Tsim Apiak.
-#
-# Tsim Apiak is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public Licence as published by
-# the Free Software Foundation, either version 3 of the Licence, or
-# (at your option) any later version.
-#
-# In addition to this, you must also comply with clause 4 of the
-# Apache Licence, version 2.0, concerning attribution. Where there
-# is a contradiction between the two licences, the GPL
-# takes preference.
-#
-# Tsim Apiak 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 Tsim Apiak. If not, see .
-
-from tsimapiak import translate
-import sys
-
-for line in sys.stdin:
- for word in translate.translatesent(line, "eng"):
- translated.append(word["translated"])
- translated = nm_to_n(e.source()) + ": " + " | ".join(translated)
- print translated
-
/cliapp/tsimapiakcli.py
Property changes:
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Index: dev/naviparse.py
===================================================================
--- dev/naviparse.py (nonexistent)
+++ dev/naviparse.py (revision 48)
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+import re
+
+strings = [ u"oe", u"nga", u"k<0><1>am<2>e", u"t<0><1><2>ìng nari", u"s<0><1><2>i", u"t<0><1><2>ìng" ]
+
+infixes0 = [ u"awn", u"eyk", u"us", u"äp" ]
+infixes1 = [ u"ìyev", u"iyev", u"arm", u"asy", u"ilv", u"ìmv", u"imv" u"ìrm", u"irv", u"ìsy", u"aly", u"ary", u"ìly", u"ìry", u"ìlm", u"alm", u"am", u"ay", u"er", u"ìm", u"iv", u"ìy", u"ol" ]
+infixes2 = [ u"äng", u"ats", u"eiy", u"ei", u"uy" ]
+
+# Returns array with Word,Infix 0,Infix 1,Infix 2,Case,Gender,Number suffixes,Inclusive,Indefinite,Vocative (suffix),Plural,Adposition,Adject pre,Adject suff,am/ay/tu/vi/yu,adverbial,nominalise,sä,fne,lenited?
+def parsefix(original):
+ realword = u""
+ infix0 = u""
+ infix1 = u""
+ infix2 = u""
+ infix01 = u""
+ infix_1 = u""
+ infix_2 = u""
+ for eachword in strings:
+ regex = re.sub(u" ",u"[^ ]* [^ ]*",eachword)
+ regex = re.sub(u"^",u"[^ ]*",regex)
+ regex = re.sub(u"$",u"[^ ]*",regex)
+ regex = re.sub(u"<0><1>",u"[^ ]*",regex)
+ regex = re.sub(u"<2>",u"[^ ]*",regex)
+ if re.match(regex,original):
+ realword = eachword
+ break
+ if realword == u"":
+ return [u"[" + original + u"]",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u""]
+ else:
+ if re.search(u"<",realword):
+ beginning = re.sub(u"<0><1>.*",u"",realword)
+ middle = re.sub(u".*<0><1>(.*)<2>.*",ur"\1",realword)
+ end = re.sub(u".*<2>",u"",realword)
+ infix01 = re.sub(u".*?" + re.sub(u"<0><1>",u"([^ ]*)",re.sub(u"<2>",u"[^ ]*",realword)) + u".*?",ur"\1",original)
+ infix_2 = re.sub(u".*?" + re.sub(u"<2>",u"([^ ]*)",re.sub(u"<0><1>",u"[^ ]*",realword)) + u".*?",ur"\1",original)
+ for eachinfix in infixes0:
+ if infix01.startswith(eachinfix):
+ infix0 = eachinfix
+ infix_1 = infix01[len(eachinfix):]
+ break
+ else:
+ infix0 = u""
+ infix_1 = infix01
+ gotinfix1 = False
+ for eachinfix in infixes1:
+ if infix_1.startswith(eachinfix):
+ infix1 = eachinfix
+ infix_1 = infix_1[len(eachinfix):]
+ if infix_1 != u"":
+ if re.search(u"<0><1><2>",realword):
+ infix_2 = infix_1
+ else:
+ return [u"[" + original + u"]",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u""]
+ gotinfix1 = True
+ break
+ if gotinfix1 == False:
+ if re.search(u"<0><1><2>",realword):
+ if infix_1 == u"":
+ infix_2 = infix_1
+ infix1 = u""
+ elif infix_1 == u"":
+ infix1 = u""
+ else:
+ return [u"[" + original + u"]",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u""]
+ gotinfix2 = False
+ for eachinfix in infixes2:
+ if infix_2.startswith(eachinfix):
+ infix2 = infix_2
+ gotinfix2 = True
+ break
+ if gotinfix2 == False:
+ if infix_2.startswith(end):
+ suffixes = infix2[len(end) - 1:] + end
+ elif infix_2 == u"":
+ infix2 = u""
+ else:
+ return [u"[" + original + u"]",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u""]
+# print u"0" + unicode(infix0) + u" 1" + unicode(infix1) + u" 2" + unicode(infix2)
+ return [realword,infix0,infix1,infix2,u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u""]
+ else:
+ return [realword,u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u"",u""]
+
+print parsefix(u"oel")
+print parsefix(u"ngati")
+print parsefix(u"kameie")
+print parsefix(u"kìyevame")
+print parsefix(u"English")
+print parsefix(u"keykivame")
+print parsefix(u"tìsusiti")
+print parsefix(u"tayìng nari")
+print parsefix(u"tìtusìng")
Index: webapp/static/favicon.ico
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: webapp/static/favicon.ico
===================================================================
--- webapp/static/favicon.ico (revision 248)
+++ webapp/static/favicon.ico (nonexistent)
/webapp/static/favicon.ico
Property changes:
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: webapp/main.py
===================================================================
--- webapp/main.py (revision 248)
+++ webapp/main.py (revision 48)
@@ -1,37 +1,20 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-# This file is part of Tsim Apiak.
-#
-# Tsim Apiak is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public Licence as published by
-# the Free Software Foundation, either version 3 of the Licence, or
-# (at your option) any later version.
-#
-# In addition to this, you must also comply with clause 4 of the
-# Apache Licence, version 2.0, concerning attribution. Where there
-# is a contradiction between the two licences, the GPL
-# takes preference.
-#
-# Tsim Apiak 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 Tsim Apiak. If not, see .
-
-from tsimapiak import parse, parsenum, translate
-import httplib
-import os
import tornado.httpserver
import tornado.ioloop
import tornado.web
+import tornado.autoreload
+import os
+import re
+from tsimapiak.parsenum import parse
+from tsimapiak.dbconnector import getnavilist
+
class Index(tornado.web.RequestHandler):
def get(self):
- self.render("templates/index.html")
+ self.redirect("/number")
class Number(tornado.web.RequestHandler):
def get(self):
@@ -42,69 +25,32 @@
num = self.get_argument("num").strip()
except:
self.redirect("/number")
- numout = parsenum.parse(num.replace(" ", ""))
+ numout = parse(num.replace(" ",""))
if numout == None:
- numoutt = -1
- else:
- numoutt = (numout["dec"], numout["oct"])
- self.render("templates/number.html", last=num, numout=numoutt)
+ numout = -1
+ self.render("templates/number.html", last=num, numout=numout)
class Restart(tornado.web.RequestHandler):
def get(self):
os.system("/usr/bin/restartnavi")
-class Parse(tornado.web.RequestHandler):
- def get(self):
- self.render("templates/parse.html", last="", out=None)
- def post(self):
- try:
- word = self.get_argument("word")
- except:
- self.redirect("/parse")
- out = parse.parsesent(word)
- self.render("templates/parse.html", last=word, out=out)
-
-class Translate(tornado.web.RequestHandler):
+class TestDB(tornado.web.RequestHandler):
def get(self):
- self.render("templates/translate.html", last="", out=None, lang="eng")
+ lis = getnavilist()
+ text = u"id | navi | infix | partofspeech
"
+ text += u"
".join(u" | ".join(unicode(y) for y in x) for x in lis)
+ self.write(text)
- def post(self):
- try:
- word = self.get_argument("word")
- lang = self.get_argument("lang")
- except:
- self.redirect("/translate")
- out = translate.translatesent(word, lang)
- self.render("templates/translate.html", last=word, out=out, lang=lang)
-class Errors(tornado.web.RequestHandler):
- def get_error_html(self, status_code, **kwargs):
- if status_code == 500:
- return "%(code)d: %(message)s" \
- "%(code)d: %(message)s

Either we are currently working on the server, or you uncovered a bug. Please check back later on. If you still get this error, please report this bug to us in the forum thread or on IRC." % {
- "code": status_code,
- "message": httplib.responses[status_code],
- }
- else:
- return "%(code)d: %(message)s" \
- "%(code)d: %(message)s" % {
- "code": status_code,
- "message": httplib.responses[status_code],
- }
-
-settings = {
- "static_path": os.path.join(os.path.dirname(__file__), "static")
-}
-
application = tornado.web.Application([
("/", Index),
("/number", Number),
("/restart", Restart),
- ("/parse", Parse),
- ("/translate", Translate)
-], **settings)
+ ("/testdb", TestDB)
+])
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(1337)
+ tornado.autoreload.start()
tornado.ioloop.IOLoop.instance().start()
/webapp/templates/translate.html
File deleted
/webapp/templates/index.html
File deleted
/webapp/templates/parse.html
File deleted
/webapp/templates/base.html
1,28 → 1,6
<html>
<!--
# This file is part of Tsim Apiak.
#
# Tsim Apiak is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public Licence as published by
# the Free Software Foundation, either version 3 of the Licence, or
# (at your option) any later version.
#
# In addition to this, you must also comply with clause 4 of the
# Apache Licence, version 2.0, concerning attribution. Where there
# is a contradiction between the two licences, the GPL
# takes preference.
#
# Tsim Apiak 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 Tsim Apiak. If not, see <http://www.gnu.org/licenses/>.
-->
<head>
<title>Tsim Apiak - {% block title %}Title{% end %}</title>
<link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico" />
<style type="text/css">
body {
background: #145179;
52,7 → 30,6
<body>
<div id="center">
<h1>Tsim Apiak</h1>
<h2>By Sh4rK and Muzer</h2>
<h2>{% block title %}Title{% end %}</h2>
{% block body %}Body{% end %}
</div>
/webapp/templates/number.html
3,28 → 3,6
{% block title %}Number translator{% end %}
 
{% block body %}
<!--
# This file is part of Tsim Apiak.
#
# Tsim Apiak is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public Licence as published by
# the Free Software Foundation, either version 3 of the Licence, or
# (at your option) any later version.
#
# In addition to this, you must also comply with clause 4 of the
# Apache Licence, version 2.0, concerning attribution. Where there
# is a contradiction between the two licences, the GPL
# takes preference.
#
# Tsim Apiak 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 Tsim Apiak. If not, see <http://www.gnu.org/licenses/>.
-->
 
<b>Na'vi number:</b><br />
<form action="/number" method="post">
<input id="num" name="num" type="text" value="{{last}}" style="width: 100%;" />
/tsimapiak/parse.py
File deleted
/tsimapiak/translate.py
File deleted
/tsimapiak/dbconnector.py
1,53 → 1,52
#!/usr/bin/python
# -*- coding: utf-8 -*-
# This file is part of Tsim Apiak.
#
# Tsim Apiak is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public Licence as published by
# the Free Software Foundation, either version 3 of the Licence, or
# (at your option) any later version.
#
# In addition to this, you must also comply with clause 4 of the
# Apache Licence, version 2.0, concerning attribution. Where there
# is a contradiction between the two licences, the GPL
# takes preference.
#
# Tsim Apiak 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 Tsim Apiak. If not, see <http://www.gnu.org/licenses/>.
 
 
import tornado.database
import re
 
def getnavilist():
ret = []
current = u""
db = tornado.database.Connection("127.0.0.1", "navi", user="navi", password="navi")
for row in db.query("""
SELECT *
SELECT *, CHAR_LENGTH(navi) AS NL
FROM `metaWords`
WHERE partOfSpeech <> 'num.' AND partOfSpeech <> "prefix"
ORDER BY CHAR_LENGTH(navi) DESC"""):
if row["infixes"]:
ret.append({"id": row["id"], "navi": row["navi"], "infix": row["infixes"].lower(), "type": row["partOfSpeech"]})
ORDER BY NL DESC"""):
if row["partOfSpeech"] in (u"v.", u"vin.", u"vtr."):
current = unicode(row["ipa"])
current = current.replace(ur"ɛ",ur"e").replace(ur".",ur"").replace(ur"ɾ",ur"r") \
.replace(ur"ɪ",ur"ì").replace(ur"ˈ",ur"").replace(ur"'",ur"x") \
.replace(ur"ŋ",ur"ng").replace(ur"j",ur"y").replace(ur"ʔ",ur"'") \
.replace(ur"æ",ur"ä").replace(ur"ˌ",ur"").replace(ur"\t{ts}",ur"ts") \
.replace(ur"ṛ",ur"rr").replace(ur"ḷ",ur"ll").replace(ur"k̚",ur"k ") \
.replace(ur"p̚",ur"p ").replace(ur"t̚",ur"t ").replace(ur"'̚",ur"' ") \
.replace(u"\\",ur"").replace(ur"(",ur"").replace(ur")",ur"") \
.replace(ur"[",ur"").replace(ur"]",ur"").replace(ur" "," ") \
.strip()
current = re.sub(ur" or.*","",current)
current = re.sub(ur"z(.*)engk(.*)e",ur"z\1enk\2e",current)
current = re.sub(ur"t(.*)ì(m|n)\ ",ur"t\1ìng ",current)
current = current.split(ur"$cdot$")
if len(current) == 3:
current = current[0] + u"<0><1>" + current[1] + u"<2>" + current[2]
elif len(current) == 2:
current = current[0] + u"<0><1><2>" + current[1]
else:
ret.append({"id": row["id"], "navi": row["navi"], "infix": row["navi"].lower(), "type": row["partOfSpeech"]})
current = u"<0><1><2>" + current[0]
else:
current = unicode(row["navi"])
ret.append([row["id"], row["navi"], current, row["partOfSpeech"]])
db.close()
return ret
 
def translate(wid, language):
ret = None
def getnavi(word):
ret = []
db = tornado.database.Connection("127.0.0.1", "navi", user="navi", password="navi")
for row in db.query("""
SELECT *
FROM `localizedWords`
WHERE id = %s AND languageCode = %s""", wid, language):
ret = row["localized"]
break
if ret == None:
return u"ERROR: WORD NOT LOCALISED"
FROM `metaWords`
WHERE navi = ?""",word):
ret.append([row["id"],row["navi"], row["infix"], row["partOfSpeech"]])
db.close()
return ret
/tsimapiak/parsenum.py
1,164 → 1,81
#!/usr/bin/python
# -*- coding: utf-8 -*-
# This file is part of Tsim Apiak.
#
# Tsim Apiak is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public Licence as published by
# the Free Software Foundation, either version 3 of the Licence, or
# (at your option) any later version.
#
# In addition to this, you must also comply with clause 4 of the
# Apache Licence, version 2.0, concerning attribution. Where there
# is a contradiction between the two licences, the GPL
# takes preference.
#
# Tsim Apiak 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 Tsim Apiak. If not, see <http://www.gnu.org/licenses/>.
 
NUM = [u"kew",
u"'aw",
u"mune",
u"pxey",
u"tsìng",
u"mrr",
u"pukap",
u"kinä"]
 
NUMORD = [u"kew",
u"'aw",
u"mu",
u"pxey",
u"tsì",
u"mrr",
u"pu",
u"ki"]
 
REM = [u"aw",
u"mun",
u"pey",
u"sìng",
u"mrr",
u"fu",
u"hin"]
 
REMORD = [u"aw",
u"mu",
u"pey",
u"sì",
u"mrr",
u"fu",
u"hi"]
 
BASE = [u"",
u"me",
u"pxe",
u"tsì",
u"mrr",
u"pu",
u"ki"]
 
def parse(numin):
if u"mm" in numin:
return None
if (numin == u"") or ((numin[0] == u"a") and (numin[len(numin) - 1] == u"a")):
return None
prefs = []
posts = []
outoct = 0
outdec = 0
ret = {"word": {"id": 0, "navi": u"", "infix": u"", "type": u""}, "pref": [prefs], "post": [posts], "inf": [u"", u"", u""], "len": False, "dec": outdec, "oct": outoct}
if numin[0] == u"a":
prefs.append(u"a")
numin = numin[1:]
if numin[len(numin) - 1] == u"a":
posts.append(u"a")
numin = numin[:-1]
if numin[-2:] == u"ve":
posts.append(u"ve")
numin = numin[:-2]
 
#BASE numbers
for n in range(len(NUM)):
if u"ve" in posts:
if numin == NUMORD[n]:
outoct = n
outdec = n
ret["word"]["navi"] = unicode(outdec) + u"."
ret["dec"] = outdec
ret["oct"] = outoct
return ret
else:
if numin == NUM[n]:
outoct = n
outdec = n
ret["word"]["navi"] = unicode(outdec)
ret["dec"] = outdec
ret["oct"] = outoct
return ret
#other numbers
notbase = False
for n in range(len(BASE)):
if numin.startswith(BASE[n] + u"zazam"):
outoct += (n + 1) * (10 ** 4)
outdec += (n + 1) * (8 ** 4)
if numin[len(BASE[n]) + 4:].startswith(u"mrr") or numin[len(BASE[n]) + 4:].startswith(u"me"):
numin = numin[len(BASE[n]) + 4:]
else:
numin = numin[len(BASE[n]) + 5:]
notbase = True
for n in range(len(BASE)):
if numin.startswith(BASE[n] + u"vozam"):
outoct += (n + 1) * (10 ** 3)
outdec += (n + 1) * (8 ** 3)
if numin[len(BASE[n]) + 4:].startswith(u"mrr") or numin[len(BASE[n]) + 4:].startswith(u"me"):
numin = numin[len(BASE[n]) + 4:]
else:
numin = numin[len(BASE[n]) + 5:]
notbase = True
for n in range(len(BASE)):
if numin.startswith(BASE[n] + u"zam"):
outoct += (n + 1) * (10 ** 2)
outdec += (n + 1) * (8 ** 2)
if numin[len(BASE[n]) + 2:].startswith(u"mrr") or numin[len(BASE[n]) + 2:].startswith(u"me"):
numin = numin[len(BASE[n]) + 2:]
else:
numin = numin[len(BASE[n]) + 3:]
notbase = True
for n in range(len(BASE)):
if numin.startswith(BASE[n] + u"vol"):
outoct += (n + 1) * 10
outdec += (n + 1) * 8
numin = numin[len(BASE[n]) + 3:]
notbase = True
if numin.startswith(BASE[n] + u"vo"):
outoct += (n + 1) * 10
outdec += (n + 1) * 8
numin = numin[len(BASE[n]) + 2:]
notbase = True
if notbase:
for n in range(len(REM)):
if u"ve" in posts:
if numin == REMORD[n]:
outoct += n + 1
outdec += n + 1
numin = u""
else:
if numin == REM[n]:
outoct += n + 1
outdec += n + 1
numin = u""
if numin == u"":
ret["word"]["navi"] = unicode(outdec) if not u"ve" in posts else unicode(outdec) + u"."
ret["dec"] = outdec
ret["oct"] = outoct
return ret
else:
return None
 
if __name__ == "__main__":
print parse(u"mevolawve")
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import re
 
num = [u"kew",
u"'aw",
u"mune",
u"pxey",
u"tsìng",
u"mrr",
u"pukap",
u"kinä"]
 
rem = [u"aw",
u"mun",
u"pey",
u"sìng",
u"mrr",
u"fu",
u"hin"]
 
base = [u"",
u"me",
u"pxe",
u"tsì",
u"mrr",
u"pu",
u"ki"]
 
 
numre = \
u"^(?:(" + "|".join(base) + u")zazam??)?" + \
u"(?:(" + "|".join(base) + u")vozam??)?" + \
u"(?:(" + "|".join(base) + u")zam??)?" + \
u"(?:(" + "|".join(base) + u")vo(?:l(?=a|))?)?" + \
u"((?:" + "|".join(rem) + u")|" + \
u"(?:" + "|".join(num) + u"))?$"
numre = re.compile(numre)
 
def parse(numin):
if type(numin) != unicode:
return None
if numin == u"":
return None
numin = numin.replace(u"í",u"ì").replace(u"á",u"ä")
try:
mat = numre.match(numin).groups()
except:
return None
numout = 0
numoct = 0
try:
numout += rem.index(mat[4]) + 1
numoct += rem.index(mat[4]) + 1
except:
try:
numout += num.index(mat[4])
numoct += num.index(mat[4])
except: pass
try:
numout += (base.index(mat[3]) + 1) * 8
numoct += (base.index(mat[3]) + 1) * 10
except: pass
try:
numout += (base.index(mat[2]) + 1) * 8**2
numoct += (base.index(mat[2]) + 1) * 10**2
except: pass
try:
numout += (base.index(mat[1]) + 1) * 8**3
numoct += (base.index(mat[1]) + 1) * 10**3
except: pass
try:
numout += (base.index(mat[0]) + 1) * 8**4
numoct += (base.index(mat[0]) + 1) * 10**4
except: pass
return numout, numoct
 
 
if __name__ == "__main__":
print parse(u"mrrvolaw")
/tsimapiak/__init__.py
File deleted