diff --git a/configure.ac b/configure.ac index d61f24b4..b7b348cd 100644 --- a/configure.ac +++ b/configure.ac @@ -69,9 +69,7 @@ services/console/lib/Makefile services/console/lib/graphics/Makefile services/console/lib/procmem/Makefile services/console/lib/net/Makefile -services/console/lib/gui/Makefile -services/console/lib/purk/Makefile -services/console/lib/purk/scripts/Makefile +services/console/lib/ui/Makefile services/console/Makefile services/console/interface/Makefile services/console/interface/xo/Makefile @@ -84,7 +82,6 @@ services/console/interface/memphis/Makefile services/console/interface/network/Makefile services/console/interface/logviewer/Makefile services/console/interface/terminal/Makefile -services/console/interface/irc_client/Makefile sugar/Makefile sugar/activity/Makefile sugar/clipboard/Makefile diff --git a/services/console/console.py b/services/console/console.py index cf33a765..4fb36095 100755 --- a/services/console/console.py +++ b/services/console/console.py @@ -30,7 +30,7 @@ CONSOLE_BUS = 'org.laptop.sugar.Console' CONSOLE_PATH = '/org/laptop/sugar/Console' CONSOLE_IFACE = 'org.laptop.sugar.Console' -class Console(object): +class Console: def __init__(self): # Main Window @@ -54,7 +54,6 @@ class Console(object): self._load_interface('memphis', 'Memphis') self._load_interface('logviewer', 'Log Viewer') self._load_interface('terminal', 'Terminal') - self._load_interface('irc_client', 'IRC') self._load_interface('ps_watcher', 'Presence') main_hbox = gtk.HBox() @@ -91,4 +90,5 @@ bus = dbus.SessionBus() name = dbus.service.BusName(CONSOLE_BUS, bus) obj = Service(name) + gtk.main() diff --git a/services/console/interface/Makefile.am b/services/console/interface/Makefile.am index 628ab2cd..ef0f3e4f 100644 --- a/services/console/interface/Makefile.am +++ b/services/console/interface/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = irc_client memphis network logviewer terminal xo +SUBDIRS = memphis network logviewer terminal xo sugardir = $(pkgdatadir)/services/console/interface sugar_PYTHON = \ diff --git a/services/console/interface/irc_client/Makefile.am b/services/console/interface/irc_client/Makefile.am deleted file mode 100644 index 934d9afd..00000000 --- a/services/console/interface/irc_client/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -sugardir = $(pkgdatadir)/services/console/interface/irc_client -sugar_PYTHON = \ - __init__.py \ - irc_client.py - diff --git a/services/console/interface/irc_client/__init__.py b/services/console/interface/irc_client/__init__.py deleted file mode 100644 index 5f8fa13e..00000000 --- a/services/console/interface/irc_client/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from irc_client import Interface - diff --git a/services/console/interface/irc_client/irc_client.py b/services/console/interface/irc_client/irc_client.py deleted file mode 100644 index a7189594..00000000 --- a/services/console/interface/irc_client/irc_client.py +++ /dev/null @@ -1,10 +0,0 @@ -import purk - -class Interface(object): - def __init__(self): - client = purk.Client() - client.show() - client.join_server('irc.freenode.net') - self.widget = client.get_widget() - - diff --git a/services/console/interface/network/network.py b/services/console/interface/network/network.py index ecd09aa9..1f226905 100644 --- a/services/console/interface/network/network.py +++ b/services/console/interface/network/network.py @@ -17,7 +17,7 @@ import gobject from net.device import Device -from gui.treeview import TreeView +from ui.treeview import TreeView class NetworkView(TreeView): def __init__(self): diff --git a/services/console/interface/xo/cpu.py b/services/console/interface/xo/cpu.py index 30a2ca34..6f6a5a79 100644 --- a/services/console/interface/xo/cpu.py +++ b/services/console/interface/xo/cpu.py @@ -101,6 +101,7 @@ class XO_CPU(gtk.Frame): gobject.timeout_add(self._DRW_CPU.frequency, self._update_cpu_usage) def _update_cpu_usage(self): + print "update XO CPU" self._cpu = self._DRW_CPU._get_CPU_usage() self.set_label('System CPU Usage: ' + str(self._cpu) + '%') diff --git a/services/console/lib/Makefile.am b/services/console/lib/Makefile.am index 02014465..0d4dcce2 100644 --- a/services/console/lib/Makefile.am +++ b/services/console/lib/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = procmem graphics net gui purk +SUBDIRS = procmem graphics net ui sugardir = $(pkgdatadir)/shell/console/lib sugar_PYTHON = diff --git a/services/console/lib/gui/Makefile.am b/services/console/lib/gui/Makefile.am deleted file mode 100644 index c045c9eb..00000000 --- a/services/console/lib/gui/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -sugardir = $(pkgdatadir)/services/console/lib/gui - -sugar_PYTHON = \ - __init__.py \ - treeview.py diff --git a/services/console/lib/gui/__init__.py b/services/console/lib/gui/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/services/console/lib/gui/treeview.py b/services/console/lib/gui/treeview.py deleted file mode 100644 index 5f5dc968..00000000 --- a/services/console/lib/gui/treeview.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (C) 2007, Eduardo Silva -# -# 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 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. - -import gtk - -class TreeView(gtk.ScrolledWindow): - iters = [] # Iters index - - # Create a window with a treeview object - # - # cols = List of dicts, ex: - # - # cols = [] - # cols.append({'index': integer_index_position, 'name': string_col_name}) - def __init__(self, cols_def, cols_name): - gtk.ScrolledWindow.__init__(self) - - self._iters = [] - self._treeview = gtk.TreeView() - - # Creating column data types - self._store = gtk.TreeStore(*cols_def) - - # Columns definition - cell = gtk.CellRendererText() - tv_cols = [] - - i=0 - for col in cols_name: - col_tv = gtk.TreeViewColumn(col['name'], cell, text=i) - col_tv.set_reorderable(True) - col_tv.set_resizable(True) - tv_cols.append(col_tv) - i+=1 - - # Setting treeview properties - self._treeview.set_model(self._store) - self._treeview.set_enable_search(True) - self._treeview.set_rules_hint(True) - - for col in tv_cols: - self._treeview.append_column(col) - self.add(self._treeview) - - def add_row(self, cols_data): - iter = self._store.insert_after(None, None) - for col in cols_data: - print col['index'],col['info'] - self._store.set_value(iter, int(col['index']) , col['info']) - - self.iters.append(iter) - return iter - - def update_row(self, iter, cols_data): - for col in cols_data: - self._store.set_value(iter, int(col['index']) , str(col['info'])) - - def remove_row(self, iter): - self._store.remove(iter) diff --git a/services/console/lib/purk/ABOUT b/services/console/lib/purk/ABOUT deleted file mode 100644 index d1683db1..00000000 --- a/services/console/lib/purk/ABOUT +++ /dev/null @@ -1,7 +0,0 @@ -Urk is a PyGTK IRC Client written by Vincent Povirk and Marc Liddell. -This current version has been modified in order to have an PyGTK -IRC Client Widget called 'Purk'. - -Suggestions are welcome... - -Eduardo Silva diff --git a/services/console/lib/purk/COPYING b/services/console/lib/purk/COPYING deleted file mode 100644 index 3912109b..00000000 --- a/services/console/lib/purk/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/services/console/lib/purk/Makefile.am b/services/console/lib/purk/Makefile.am deleted file mode 100644 index 33fe5957..00000000 --- a/services/console/lib/purk/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -SUBDIRS = scripts -sugardir = $(pkgdatadir)/services/console/lib/purk - -sugar_PYTHON = \ - __init__.py \ - conf.py \ - events.py \ - info.py \ - irc.py \ - parse_mirc.py \ - servers.py \ - ui.py \ - urk_trace.py \ - widgets.py \ - windows.py \ - README \ - ABOUT diff --git a/services/console/lib/purk/README b/services/console/lib/purk/README deleted file mode 100644 index 9e55cca0..00000000 --- a/services/console/lib/purk/README +++ /dev/null @@ -1,186 +0,0 @@ -urk 0.-1.cvs -http://urk.sourceforge.net/ - - -Overview: - -urk is an IRC client written purely in python for linux/gnome. It has a powerful -built-in scripting system (also python), which is used to implement much of the -client. - - -Requirements/User installation: - -urk requires the following packages (and should run on any os that can provide -them): --python version 2.4 or greater (www.python.org) --pygtk 2.6 or greater (www.pygtk.org) - -Most Linux (or at least GNOME) users should have these things already or be able -to easily install them. - -Because urk is pure python, no compilation of urk is required. Just extract the -source to somewhere and run 'python urk.py'. - -Windows versions of the above should theoretically work but may not in practice. -I am hoping someone will come along and actually support urk on windows. - - -Optional requirements: - -urk can also make use of these packages if you have them: --pygtksourceview, part of gnome-python-extras <=2.12 and gnome-python-desktop - >=2.14, for source highlighting and undo in the internal script editor --python-dbus, for, well, not much (if dbus is available, urk only makes a single - instance per session, and commands can be executed remotely by calling urk.py) - - -Getting started: - -Make sure you have all the requirements, go to the directory where you have -extracted the source, and type 'python urk.py'. - -We don't have any preferences windows yet. You can change your nickname by -typing '/nick nickname' (replacing nickname with the nick you want to use) -or typing a new nick in the nick field on the lower right corner and pressing -enter. - -To connect, type '/server irc.gamesurge.net' (replacing irc.gamesurge.net with -the server you want to connect to). - -If you want to connect to another server (without disconnecting the current -one), use the -m switch as in '/server -m irc.gamesurge.net'. - -To join a channel when you're connected to a server, type '/join #channelname', -replacing #channelname with the channel you want to join. - -urk currently only supports the bare minimum commands and features you should -need to connect and chat normally. On channels, you can send messages by -typing them (if you want to send a message that starts with a /, use /say to -send your message). You can send actions to channels with /me and send messages -to arbitrary targets with /msg. If urk does not recognize a command, it will -send it to the server. This works to implement most commands you would expect -on an irc client. - - -Configuration: - -Most configuration has to be done manually. If urk is running, you can configure -it using commands. The settings are stored in urk.conf on your profile -directory, which you can locate by typing '/pyeval urk.userpath' in urk. - -To set a value in urk, type - -/pyexec conf.conf['setting'] = value - -To see the current value, type - -/pyeval conf.conf['setting'] - -To unset a value (meaning urk will use the default), type - -/pyexec del conf.conf['setting'] - -Setting: Description: - -'nick' The nickname urk should use. The default is to try to get - it from the os. Put this in quotes when you set it. - -'altnicks' A list of alternative nicknames to use. The default is - an empty list. - -'quitmsg' The message people see when you quit. The default is to - advertise urk with your current version; we have to promote it somehow. - This value needs to be in quotes. - -'autoreconnect' If True, urk will try to reconnect when you're - disconnected from a network. Defaults to True. Set this to True or False. - -'highlight_words' A list of words, in addition to your nick, that cause a - highlight event (normally the tab label turns blue and, if it's available, - the tray icon shows up). For example: ['python', 'whale', 'peanut butter'] - -'log_dir' The place where logs are written. The default is a - directory called "logs" on your profile directory. - -'ui-gtk/tab-pos' The side of the window where the tabs will reside - 2 for top - 0 for left - 1 for right - 3 for bottom (default) - -'ui-gtk/show-menubar' If True, the menubar is shown. The default is True. Set - this to True or False. - -'command_prefix' The prefix used to signal a command. Defaults to '/' - -'font' The font used for output. Defaults to "sans 8". - -'bg_color' The background color ("black" or "#000000"). - -'fg_color' The foreground color ("white" or "#ffffff"). - -'timestamp' A timestamp that will show up before messages. The - default is no timestamp. A simple timestamp with hours and minutes is - "[%H:%M] ". See http://docs.python.org/lib/module-time.html#l2h-1955 for - a key to format this string. - -'start-console' If True, urk will start up with a special console window - that shows debugging output (normally sent to a terminal) and accepts - python expressions. Defaults to False. - -'status' If True, urk will be in status window mode. Each network - will ALWAYS have a status window. When not in status window mode, networks - only have a status window when there are no channel windows. Defaults to - False. - -'open-file-command' The command used to open files and url's with your - preferred application (such as "gnome-open"). This is ignored on Windows, - and you should never need to mess with this, ever. - - -System-wide installation: - -Not yet implemented. - - -About scripting: - -urk scripts are python source files that contain definitions of functions with -certain "magic" names, like onText (for when someone sends a channel or private -message). See www.python.org for help on writing python code. The format for -onText is: - -def onText(e): - code - -e is an object used to pass on the various information relating to the event -that triggered the function. The name is a convention we use, much like self. - -e.source is the nickname of the person who sent the message. - -e.target is the nickname or channel that received the message. - -e.text is the text of the message. - -e.network is an object representing the network where the message was sent. - -e.window is a window that seems to be related to the event for some unspecified -reason. It could be the status window, a channel window, a query, anything. - -Complete documentation doesn't exist yet. Sorry. Ask us or look at the source. theme.py is good for finding event names. - - -Bugs/Feedback: - -Naturally, feedback of any sort is welcome. Of course we want to know about -bugs. In particular, we'd also like to hear about any features you want or -expect in an irc client that urk doesn't have. While we'd like to limit the -things that go in the default client (a notify list, for example, is something -we'd want to see as an external script, not as part of the default setup, and -something we're not likely to implement soon), there are probably a lot of -little things that we may have skipped over because we don't use them or have -become used to urk not having them. - -The best way to get in touch with us is by irc, at #urk on irc.gamesurge.net. -Or send a message to the mailing list, urk-discussion@lists.sourceforge.net. diff --git a/services/console/lib/purk/UrkLogQueryable.cs b/services/console/lib/purk/UrkLogQueryable.cs deleted file mode 100644 index ee0611c2..00000000 --- a/services/console/lib/purk/UrkLogQueryable.cs +++ /dev/null @@ -1,245 +0,0 @@ -using System; -using System.Collections; -using System.IO; -using System.Text; -using System.Threading; - -using Beagle.Daemon; -using Beagle.Util; - -namespace Beagle.Daemon.UrkLogQueryable { - - [QueryableFlavor (Name="UrkLog", Domain=QueryDomain.Local, RequireInotify=false)] - public class UrkLogQueryable : LuceneFileQueryable { - - private static Logger log = Logger.Get ("UrkLogQueryable"); - - private string config_dir, log_dir, icons_dir; - - private int polling_interval_in_seconds = 60; - - //private GaimBuddyListReader list = new GaimBuddyListReader (); - - public UrkLogQueryable () : base ("UrkLogIndex") - { - config_dir = Path.Combine (PathFinder.HomeDir, ".urk"); - log_dir = Path.Combine (config_dir, "logs"); - icons_dir = Path.Combine (config_dir, "icons"); - } - - ///////////////////////////////////////////////// - - private void StartWorker() - { - if (! Directory.Exists (log_dir)) { - GLib.Timeout.Add (60000, new GLib.TimeoutHandler (CheckForExistence)); - return; - } - - log.Info ("Starting urk log backend"); - - Stopwatch stopwatch = new Stopwatch (); - stopwatch.Start (); - - State = QueryableState.Crawling; - Crawl (); - State = QueryableState.Idle; - - if (!Inotify.Enabled) { - Scheduler.Task task = Scheduler.TaskFromHook (new Scheduler.TaskHook (CrawlHook)); - task.Tag = "Crawling ~/.urk/logs to find new logfiles"; - task.Source = this; - ThisScheduler.Add (task); - } - - stopwatch.Stop (); - - log.Info ("urk log backend worker thread done in {0}", stopwatch); - } - - public override void Start () - { - base.Start (); - - ExceptionHandlingThread.Start (new ThreadStart (StartWorker)); - } - - ///////////////////////////////////////////////// - - private void CrawlHook (Scheduler.Task task) - { - Crawl (); - task.Reschedule = true; - task.TriggerTime = DateTime.Now.AddSeconds (polling_interval_in_seconds); - } - - private void Crawl () - { - Inotify.Subscribe (log_dir, OnInotifyNewProtocol, Inotify.EventType.Create); - - // Walk through protocol subdirs - foreach (string proto_dir in DirectoryWalker.GetDirectories (log_dir)) - CrawlProtocolDirectory (proto_dir); - } - - private void CrawlNetworkDirectory (string proto_dir) - { - Inotify.Subscribe (proto_dir, OnInotifyNewTarget, Inotify.EventType.Create); - - // Walk through accounts - foreach (string account_dir in DirectoryWalker.GetDirectories (proto_dir)) - CrawlTargetDirectory (account_dir); - } - - private void CrawlTargetDirectory (string account_dir) - { - Inotify.Subscribe (account_dir, OnInotifyNewRemote, Inotify.EventType.Create); - - // Walk through remote user conversations - foreach (string remote_dir in DirectoryWalker.GetDirectories (account_dir)) - CrawlRemoteDirectory (remote_dir); - } - - private void CrawlRemoteDirectory (string remote_dir) - { - Inotify.Subscribe (remote_dir, OnInotifyNewConversation, Inotify.EventType.CloseWrite); - - foreach (FileInfo file in DirectoryWalker.GetFileInfos (remote_dir)) - if (FileIsInteresting (file.Name)) - IndexLog (file.FullName, Scheduler.Priority.Delayed); - } - - ///////////////////////////////////////////////// - - private bool CheckForExistence () - { - if (!Directory.Exists (log_dir)) - return true; - - this.Start (); - - return false; - } - - private bool FileIsInteresting (string filename) - { - // Filename must be fixed length, see below - if (filename.Length < 21 || filename.Length > 22) - return false; - - // Check match on regex: ^[0-9]{4}-[0-9]{2}-[0-9]{2}\\.[0-9]{6}\\.(txt|html)$ - // e.g. 2005-07-22.161521.txt - // We'd use System.Text.RegularExpressions if they werent so much more expensive - return Char.IsDigit (filename [0]) && Char.IsDigit (filename [1]) - && Char.IsDigit (filename [2]) && Char.IsDigit (filename [3]) - && filename [4] == '-' - && Char.IsDigit (filename [5]) && Char.IsDigit (filename [6]) - && filename [7] == '-' - && Char.IsDigit (filename [8]) && Char.IsDigit (filename [9]) - && filename [10] == '.' - && Char.IsDigit (filename [11]) && Char.IsDigit (filename [12]) - && Char.IsDigit (filename [13]) && Char.IsDigit (filename [14]) - && Char.IsDigit (filename [15]) && Char.IsDigit (filename [16]) - && filename [17] == '.' - && ( (filename [18] == 't' && filename [19] == 'x' && filename [20] == 't') - || (filename [18] == 'h' && filename [19] == 't' && filename [20] == 'm' && filename [21] == 'l') - ); - } - - ///////////////////////////////////////////////// - - private void OnInotifyNewNetwork (Inotify.Watch watch, - string path, string subitem, string srcpath, - Inotify.EventType type) - { - if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0) - return; - - CrawlNetworkDirectory (Path.Combine (path, subitem)); - } - - private void OnInotifyNewTarget (Inotify.Watch watch, - string path, string subitem, string srcpath, - Inotify.EventType type) - { - if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0) - return; - - CrawlTargetDirectory (Path.Combine (path, subitem)); - } - - private void OnInotifyNewRemote (Inotify.Watch watch, - string path, string subitem, string srcpath, - Inotify.EventType type) - { - if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0) - return; - - CrawlRemoteDirectory (Path.Combine (path, subitem)); - } - - private void OnInotifyNewConversation (Inotify.Watch watch, - string path, string subitem, string srcpath, - Inotify.EventType type) - { - if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) != 0) - return; - - if (FileIsInteresting (subitem)) - IndexLog (Path.Combine (path, subitem), Scheduler.Priority.Immediate); - } - - ///////////////////////////////////////////////// - - private static Indexable IRCLogToIndexable (string filename) - { - Uri uri = UriFu.PathToFileUri (filename); - Indexable indexable = new Indexable (uri); - indexable.ContentUri = uri; - indexable.Timestamp = File.GetLastWriteTimeUtc (filename); - indexable.MimeType = GaimLog.MimeType; // XXX - indexable.HitType = "IRCLog"; - indexable.CacheContent = false; - - return indexable; - } - - private void IndexLog (string filename, Scheduler.Priority priority) - { - if (! File.Exists (filename)) - return; - - if (IsUpToDate (filename)) - return; - - Indexable indexable = IRCLogToIndexable (filename); - Scheduler.Task task = NewAddTask (indexable); - task.Priority = priority; - task.SubPriority = 0; - ThisScheduler.Add (task); - } - - override protected double RelevancyMultiplier (Hit hit) - { - return HalfLifeMultiplierFromProperty (hit, 0.25, - "fixme:endtime", "fixme:starttime"); - } - - override protected bool HitFilter (Hit hit) - { - /*ImBuddy buddy = list.Search (hit ["fixme:speakingto"]); - - if (buddy != null) { - if (buddy.Alias != "") - hit ["fixme:speakingto_alias"] = buddy.Alias; - - //if (buddy.BuddyIconLocation != "") - // hit ["fixme:speakingto_icon"] = Path.Combine (icons_dir, buddy.BuddyIconLocation); - }*/ - - return true; - } - - } -} - diff --git a/services/console/lib/purk/__init__.py b/services/console/lib/purk/__init__.py deleted file mode 100644 index 35d93ad6..00000000 --- a/services/console/lib/purk/__init__.py +++ /dev/null @@ -1,94 +0,0 @@ -import os -import sys -import traceback -import events -import windows - -urkpath = os.path.abspath(os.path.dirname(__file__)) - -if os.path.abspath(os.curdir) != os.path.join(urkpath): - sys.path[0] = os.path.join(urkpath) - -sys.path = [ - os.path.join(urkpath, "scripts"), - ] + sys.path - -script_path = urkpath+"/scripts" - -from ui import * - -# Here I'm trying to handle the original URL IRC Client, urk don't use -# normal classes . Let's try to get a urk widget: -class Trigger(object): - def __init__(self): - self._mods = [] - self.events = events - self._load_scripts() - - def _load_scripts(self): - script_path = urkpath + "/scripts" - try: - suffix = os.extsep+"py" - for script in os.listdir(script_path): - if script.endswith(suffix): - try: - mod = self.events.load(script) - self._mods.append(mod) - except: - traceback.print_exc() - print "Failed loading script %s." % script - except OSError: - pass - - def get_modules(self): - return self._mods - -class Core(object): - def __init__(self): - self.window = None - self.trigger = Trigger() - self.events = self.trigger.events - self.manager = widgets.UrkUITabs(self) - - mods = self.trigger.get_modules() - for m in mods: - m.core = self - m.manager = self.manager - - if not self.window: - self.window = windows.new(windows.StatusWindow, irc.Network(self), "status", self) - self.window.activate() - - register_idle(self.trigger_start) - gtk.gdk.threads_enter() - - def run_command(self, command): - offset = 0 - if command[0] == '/': - offset = 1 - - self.events.run(command[offset:], self.manager.get_active(), self.window.network) - - def trigger_start(self): - self.events.trigger("Start") - - def _add_script(self, module): - return - -class Client(object): - def __init__(self): - self.core = Core() - self.widget = self.core.manager.box - def run_command(self, command): - self.core.run_command(command) - - def join_server(self, network_name, port=6667): - command = 'server '+ network_name + ' ' + str(port) - self.run_command(command) - - def get_widget(self): - return self.widget - - def show(self): - self.widget.show_all() - diff --git a/services/console/lib/purk/conf.py b/services/console/lib/purk/conf.py deleted file mode 100644 index 9cae5127..00000000 --- a/services/console/lib/purk/conf.py +++ /dev/null @@ -1,86 +0,0 @@ -import os -urkpath = os.path.dirname(__file__) - -def path(filename=""): - if filename: - return os.path.join(urkpath, filename) - else: - return urkpath - -if os.access(path('profile'),os.F_OK) or os.path.expanduser("~") == "~": - userpath = path('profile') - if not os.access(userpath,os.F_OK): - os.mkdir(userpath) - if not os.access(os.path.join(userpath,'scripts'),os.F_OK): - os.mkdir(os.path.join(userpath,'scripts')) -else: - userpath = os.path.join(os.path.expanduser("~"), ".urk") - if not os.access(userpath,os.F_OK): - os.mkdir(userpath, 0700) - if not os.access(os.path.join(userpath,'scripts'),os.F_OK): - os.mkdir(os.path.join(userpath,'scripts'), 0700) - -CONF_FILE = os.path.join(userpath,'urk.conf') - - -def pprint(obj, depth=-2): - depth += 2 - - string = [] - - if isinstance(obj, dict): - if obj: - string.append('{\n') - - for key in obj: - string.append('%s%s%s' % (' '*depth, repr(key), ': ')) - string += pprint(obj[key], depth) - - string.append('%s%s' % (' '*depth, '},\n')) - - else: - string.append('{},\n') - - elif isinstance(obj, list): - if obj: - string.append('[\n') - - for item in obj: - string.append('%s' % (' '*depth)) - string += pprint(item, depth) - - string.append('%s%s' % (' '*depth, '],\n')) - - else: - string.append('[],\n') - - else: - string.append('%s,\n' % (repr(obj),)) - - if depth: - return string - else: - return ''.join(string)[:-2] - -def save(*args): - new_file = not os.access(CONF_FILE,os.F_OK) - fd = file(CONF_FILE, "wb") - try: - if new_file: - os.chmod(CONF_FILE,0600) - fd.write(pprint(conf)) - finally: - fd.close() - -#events.register('Exit', 'post', save) - -try: - conf = eval(file(CONF_FILE, "U").read().strip()) -except IOError, e: - if e.args[0] == 2: - conf = {} - else: - raise - -if __name__ == '__main__': - print pprint(conf) diff --git a/services/console/lib/purk/events.py b/services/console/lib/purk/events.py deleted file mode 100644 index 2a0d45e5..00000000 --- a/services/console/lib/purk/events.py +++ /dev/null @@ -1,298 +0,0 @@ -import sys -import os -import traceback - -pyending = os.extsep + 'py' - -class error(Exception): - pass - -class EventStopError(error): - pass - -class CommandError(error): - pass - -class data(object): - done = False - quiet = False - - def __init__(self, **kwargs): - for attr in kwargs.items(): - setattr(self, *attr) - -trigger_sequence = ("pre", "setup", "on", "setdown", "post") - -all_events = {} -loaded = {} - -# An event has occurred, the e_name event! -def trigger(e_name, e_data=None, **kwargs): - if e_data is None: - e_data = data(**kwargs) - - #print 'Event:', e_name, e_data - - failure = True - error = None - - if e_name in all_events: - for e_stage in trigger_sequence: - if e_stage in all_events[e_name]: - for f_ref, s_name in all_events[e_name][e_stage]: - try: - f_ref(e_data) - except EventStopError: - return - except CommandError, e: - error = e.args - continue - except: - traceback.print_exc() - failure = False - if failure: - print "Error handling: " + e_name - - return error - -# Stop all processing of the current event now! -def halt(): - raise EventStopError - -# Registers a specific function with an event at the given sequence stage. -def register(e_name, e_stage, f_ref, s_name=""): - global all_events - - if e_name not in all_events: - all_events[e_name] = {} - - if e_stage not in all_events[e_name]: - all_events[e_name][e_stage] = [] - - all_events[e_name][e_stage] += [(f_ref, s_name)] - -# turn a filename (or module name) and trim it to the name of the module -def get_scriptname(name): - s_name = os.path.basename(name) - if s_name.endswith(pyending): - s_name = s_name[:-len(pyending)] - return s_name - -#take a given script name and turn it into a filename -def get_filename(name): - # split the directory and filename - dirname = os.path.dirname(name) - s_name = get_scriptname(name) - - for path in dirname and (dirname,) or sys.path: - filename = os.path.join(path, s_name + pyending) - if os.access(filename, os.R_OK): - return filename - - raise ImportError("No urk script %s found" % name) - -# register the events defined by obj -def register_all(name, obj): - # we look through everything defined in the file - for f in dir(obj): - # for each bit of the event sequence - for e_stage in trigger_sequence: - - # if the function is for this bit - if f.startswith(e_stage): - # get a reference to a function - f_ref = getattr(obj, f) - #print f - # normalise to the event name - e_name = f.replace(e_stage, "", 1) - - # add our function to the right event section - register(e_name, e_stage, f_ref, name) - - break - -#load a .py file into a new module object without affecting sys.modules -def load_pyfile(filename): - s_name = get_scriptname(filename) - return __import__(s_name) - -# Load a python script and register -# the functions defined in it for events. -# Return True if we loaded the script, False if it was already loaded -def load(name): - s_name = get_scriptname(name) - filename = get_filename(name) - - if s_name in loaded: - return False - - loaded[s_name] = None - - try: - module = load_pyfile(filename) - loaded[s_name] = module - except: - del loaded[s_name] - raise - - register_all(s_name, loaded[s_name]) - - return module - -# Is the script with the given name loaded? -def is_loaded(name): - return get_scriptname(name) in loaded - -# Remove any function which was defined in the given script -def unload(name): - s_name = get_scriptname(name) - - del loaded[s_name] - - for e_name in list(all_events): - for e_stage in list(all_events[e_name]): - to_check = all_events[e_name][e_stage] - - all_events[e_name][e_stage] = [(f, m) for f, m in to_check if m != s_name] - - if not all_events[e_name][e_stage]: - del all_events[e_name][e_stage] - - if not all_events[e_name]: - del all_events[e_name] - -def reload(name): - s_name = get_scriptname(name) - - if s_name not in loaded: - return False - - temp = loaded[s_name] - - unload(s_name) - - try: - load(name) - return True - except: - loaded[s_name] = temp - register_all(s_name, temp) - raise - -def run(text, window, network): - split = text.split(' ') - - c_data = data(name=split.pop(0), text=text, window=window, network=network) - - if split and split[0].startswith('-'): - c_data.switches = set(split.pop(0)[1:]) - else: - c_data.switches = set() - - c_data.args = split - - event_name = "Command" + c_data.name.capitalize() - #print "searching: " + event_name - #for s in all_events: - # print "match: " + s - # if s == event_name: - # print "we got it!" - - if event_name in all_events: - result = trigger(event_name, c_data) - - if result: - print "* /%s: %s" % (c_data.name, result[0]) - c_data.window.write("* /%s: %s" % (c_data.name, result[0])) - else: - trigger("Command", c_data) - - if not c_data.done: - c_data.window.write("* /%s: No such command exists" % (c_data.name)) - -def onCommandPyeval(e): - loc = sys.modules.copy() - loc.update(e.__dict__) - import pydoc #fix nonresponsive help() command - old_pager, pydoc.pager = pydoc.pager, pydoc.plainpager - try: - result = repr(eval(' '.join(e.args), loc)) - if 's' in e.switches: - run( - 'say - %s => %s' % (' '.join(e.args),result), - e.window, - e.network - ) - else: - e.window.write(result) - except: - for line in traceback.format_exc().split('\n'): - e.window.write(line) - pydoc.pager = old_pager - -def onCommandPyexec(e): - loc = sys.modules.copy() - loc.update(e.__dict__) - import pydoc #fix nonresponsive help() command - old_pager, pydoc.pager = pydoc.pager, pydoc.plainpager - try: - exec ' '.join(e.args) in loc - except: - for line in traceback.format_exc().split('\n'): - e.window.write(line) - pydoc.pager = old_pager - -def onCommandLoad(e): - if e.args: - name = e.args[0] - else: - e.window.write('Usage: /load scriptname') - - try: - if load(name): - e.window.write("* The script '%s' has been loaded." % name) - else: - raise CommandError("The script is already loaded; use /reload instead") - except: - e.window.write(traceback.format_exc(), line_ending='') - raise CommandError("Error loading the script") - -def onCommandUnload(e): - if e.args: - name = e.args[0] - else: - e.window.write('Usage: /unload scriptname') - - if is_loaded(name): - unload(name) - e.window.write("* The script '%s' has been unloaded." % name) - else: - raise CommandError("No such script is loaded") - -def onCommandReload(e): - if e.args: - name = e.args[0] - else: - e.window.write('Usage: /reload scriptname') - - try: - if reload(name): - e.window.write("* The script '%s' has been reloaded." % name) - else: - raise CommandError("The script isn't loaded yet; use /load instead") - except: - e.window.write(traceback.format_exc(), line_ending='') - -def onCommandScripts(e): - e.window.write("Loaded scripts:") - for name in loaded: - e.window.write("* %s" % name) - -def onCommandEcho(e): - e.window.write(' '.join(e.args)) - -name = '' -for name in globals(): - if name.startswith('onCommand'): - register(name[2:], "on", globals()[name], '_all_events') -del name diff --git a/services/console/lib/purk/info.py b/services/console/lib/purk/info.py deleted file mode 100644 index 3765845d..00000000 --- a/services/console/lib/purk/info.py +++ /dev/null @@ -1,8 +0,0 @@ -name = "PUrk" -long_name = "Purk IRC" -version = 0, 1, "git" -long_version = "%s v%s" % (long_name, ".".join(str(x) for x in version)) -website = "http://dev.laptop.org/" -authors = ["Vincent Povirk", "Marc Liddell"] -copyright = "2005 %s" % ', '.join(authors) - diff --git a/services/console/lib/purk/irc.py b/services/console/lib/purk/irc.py deleted file mode 100644 index d5a01aad..00000000 --- a/services/console/lib/purk/irc.py +++ /dev/null @@ -1,328 +0,0 @@ -import socket -import sys - -from conf import conf -import ui -import windows -import info - -DISCONNECTED = 0 -CONNECTING = 1 -INITIALIZING = 2 -CONNECTED = 3 - -def parse_irc(msg, server): - msg = msg.split(' ') - - # if our very first character is : - # then this is the source, - # otherwise insert the server as the source - if msg and msg[0].startswith(':'): - msg[0] = msg[0][1:] - else: - msg.insert(0, server) - - # loop through the msg until we find - # something beginning with : - for i, token in enumerate(msg): - if token.startswith(':'): - # remove the : - msg[i] = msg[i][1:] - - # join up the rest - msg[i:] = [' '.join(msg[i:])] - break - - # filter out the empty pre-":" tokens and add on the text to the end - return [m for m in msg[:-1] if m] + msg[-1:] - - # note: this sucks and makes very little sense, but it matches the BNF - # as far as we've tested, which seems to be the goal - -def default_nicks(): - try: - nicks = [conf.get('nick')] + conf.get('altnicks',[]) - if not nicks[0]: - import getpass - nicks = [getpass.getuser()] - except: - nicks = ["mrurk"] - return nicks - -class Network(object): - socket = None - - def __init__(self, core, server="irc.default.org", port=6667, nicks=[], - username="", fullname="", name=None, **kwargs): - self.manager = core.manager - self.server = server - self.port = port - self.events = core.events - - self.name = name or server - - self.nicks = nicks or default_nicks() - self.me = self.nicks[0] - - self.username = username or "urk" - self.fullname = fullname or conf.get("fullname", self.username) - self.password = '' - - self.isupport = { - 'NETWORK': server, - 'PREFIX': '(ohv)@%+', - 'CHANMODES': 'b,k,l,imnpstr', - } - self.prefixes = {'o':'@', 'h':'%', 'v':'+', '@':'o', '%':'h', '+':'v'} - - self.status = DISCONNECTED - self.failedhosts = [] #hosts we've tried and failed to connect to - self.channel_prefixes = '&#+$' # from rfc2812 - - self.on_channels = set() - self.requested_joins = set() - self.requested_parts = set() - - self.buffer = '' - - #called when we get a result from the dns lookup - def on_dns(self, result, error): - if error: - self.disconnect(error=error[1]) - else: - #import os - #import random - #random.seed() - #random.shuffle(result) - if socket.has_ipv6: #prefer ipv6 - result = [(f, t, p, c, a) for (f, t, p, c, a) in result if f == socket.AF_INET6]+result - elif hasattr(socket,"AF_INET6"): #ignore ipv6 - result = [(f, t, p, c, a) for (f, t, p, c, a) in result if f != socket.AF_INET6] - - self.failedlasthost = False - - for f, t, p, c, a in result: - if (f, t, p, c, a) not in self.failedhosts: - try: - self.socket = socket.socket(f, t, p) - except: - continue - self.source = ui.fork(self.on_connect, self.socket.connect, a) - self.failedhosts.append((f, t, p, c, a)) - if set(self.failedhosts) >= set(result): - self.failedlasthost = True - break - else: - self.failedlasthost = True - if len(result): - self.failedhosts[:] = (f, t, p, c, a), - f, t, p, c, a = result[0] - try: - self.socket = socket.socket(f, t, p) - self.source = ui.fork(self.on_connect, self.socket.connect, a) - except: - self.disconnect(error="Couldn't find a host we can connect to") - else: - self.disconnect(error="Couldn't find a host we can connect to") - - #called when socket.open() returns - def on_connect(self, result, error): - if error: - self.disconnect(error=error[1]) - #we should immediately retry if we failed to open the socket and there are hosts left - if self.status == DISCONNECTED and not self.failedlasthost: - windows.get_default(self).write("* Retrying with next available host") - self.connect() - else: - self.source = source = ui.Source() - self.status = INITIALIZING - self.failedhosts[:] = () - - self.events.trigger('SocketConnect', network=self) - - if source.enabled: - self.source = ui.fork(self.on_read, self.socket.recv, 8192) - - #called when we read data or failed to read data - def on_read(self, result, error): - if error: - self.disconnect(error=error[1]) - elif not result: - self.disconnect(error="Connection closed by remote host") - else: - self.source = source = ui.Source() - - self.buffer = (self.buffer + result).split("\r\n") - - for line in self.buffer[:-1]: - self.got_msg(line) - - if self.buffer: - self.buffer = self.buffer[-1] - else: - self.buffer = '' - - if source.enabled: - self.source = ui.fork(self.on_read, self.socket.recv, 8192) - - def raw(self, msg): - self.events.trigger("OwnRaw", network=self, raw=msg) - - if self.status >= INITIALIZING: - self.socket.send(msg + "\r\n") - - def got_msg(self, msg): - pmsg = parse_irc(msg, self.server) - - e_data = self.events.data( - raw=msg, - msg=pmsg, - text=pmsg[-1], - network=self, - window=windows.get_default(self, self.manager) - ) - - if "!" in pmsg[0]: - e_data.source, e_data.address = pmsg[0].split('!',1) - - else: - e_data.source, e_data.address = pmsg[0], '' - - if len(pmsg) > 2: - e_data.target = pmsg[2] - else: - e_data.target = pmsg[-1] - - self.events.trigger('Raw', e_data) - - def connect(self): - if not self.status: - self.status = CONNECTING - - self.source = ui.fork(self.on_dns, socket.getaddrinfo, self.server, self.port, 0, socket.SOCK_STREAM) - - self.events.trigger('Connecting', network=self) - - def disconnect(self, error=None): - if self.socket: - self.socket.close() - - if self.source: - self.source.unregister() - self.source = None - - self.socket = None - - self.status = DISCONNECTED - - #note: connecting from onDisconnect is probably a Bad Thing - self.events.trigger('Disconnect', network=self, error=error) - - #trigger a nick change if the nick we want is different from the one we - # had. - if self.me != self.nicks[0]: - self.events.trigger( - 'Nick', network=self, window=windows.get_default(self), - source=self.me, target=self.nicks[0], address='', - text=self.nicks[0] - ) - self.me = self.nicks[0] - - def norm_case(self, string): - return string.lower() - - def quit(self, msg=None): - if self.status: - try: - if msg == None: - msg = conf.get('quitmsg', "%s - %s" % (info.long_version, info.website)) - self.raw("QUIT :%s" % msg) - except: - pass - self.disconnect() - - def join(self, target, key='', requested=True): - if key: - key = ' '+key - self.raw("JOIN %s%s" % (target,key)) - if requested: - for chan in target.split(' ',1)[0].split(','): - if chan == '0': - self.requested_parts.update(self.on_channels) - else: - self.requested_joins.add(self.norm_case(chan)) - - def part(self, target, msg="", requested=True): - if msg: - msg = " :" + msg - - self.raw("PART %s%s" % (target, msg)) - if requested: - for chan in target.split(' ',1)[0].split(','): - self.requested_parts.add(self.norm_case(target)) - - def msg(self, target, msg): - self.raw("PRIVMSG %s :%s" % (target, msg)) - - self.events.trigger( - 'OwnText', source=self.me, target=str(target), text=msg, - network=self, window=windows.get_default(self, self.manager) - ) - - def notice(self, target, msg): - self.raw("NOTICE %s :%s" % (target, msg)) - - self.events.trigger( - 'OwnNotice', source=self.me, target=str(target), text=msg, - network=self, window=windows.get_default(self) - ) - -#a Network that is never connected -class DummyNetwork(Network): - def __nonzero__(self): - return False - - def __init__(self, core): - Network.__init__(self, core) - - self.name = self.server = self.isupport['NETWORK'] = "None" - - def connect(self): - raise NotImplementedError, "Cannot connect dummy network." - - def raw(self, msg): - raise NotImplementedError, "Cannot send %s over the dummy network." % repr(msg) - -#dummy_network = DummyNetwork() - -#this was ported from srvx's tools.c -def match_glob(text, glob, t=0, g=0): - while g < len(glob): - if glob[g] in '?*': - star_p = q_cnt = 0 - while g < len(glob): - if glob[g] == '*': - star_p = True - elif glob[g] == '?': - q_cnt += 1 - else: - break - g += 1 - t += q_cnt - if t > len(text): - return False - if star_p: - if g == len(glob): - return True - for i in xrange(t, len(text)): - if text[i] == glob[g] and match_glob(text, glob, i+1, g+1): - return True - return False - else: - if t == len(text) and g == len(glob): - return True - if t == len(text) or g == len(glob) or text[t] != glob[g]: - return False - t += 1 - g += 1 - return t == len(text) diff --git a/services/console/lib/purk/parse_mirc.py b/services/console/lib/purk/parse_mirc.py deleted file mode 100644 index 186ff9b2..00000000 --- a/services/console/lib/purk/parse_mirc.py +++ /dev/null @@ -1,457 +0,0 @@ -try: - from conf import conf -except ImportError: - conf = {} - -BOLD = '\x02' -UNDERLINE = '\x1F' -MIRC_COLOR = '\x03' -MIRC_COLOR_BG = MIRC_COLOR, MIRC_COLOR -BERS_COLOR = '\x04' -RESET = '\x0F' - -colors = ( - '#FFFFFF', '#000000', '#00007F', '#009300', - '#FF0000', '#7F0000', '#9C009C', '#FF7F00', - '#FFFF00', '#00FF00', '#009393', '#00FFFF', - '#0000FF', '#FF00FF', '#7F7F7F', '#D2D2D2' - ) - -def get_mirc_color(number): - if number == '99': - return None - - number = int(number) & 15 - - confcolors = conf.get('colors', colors) - try: - return confcolors[number] - except: - # someone edited their colors wrongly - return colors[number] - -DEC_DIGITS, HEX_DIGITS = set('0123456789'), set('0123456789abcdefABCDEF') - -def parse_mirc_color(string, pos, open_tags, tags): - color_chars = 1 - - if MIRC_COLOR in open_tags: - fgtag = open_tags.pop(MIRC_COLOR) - fgtag['to'] = pos - tags.append(fgtag) - - if MIRC_COLOR_BG in open_tags: - bgtag = open_tags.pop(MIRC_COLOR_BG) - bgtag['to'] = pos - tags.append(bgtag) - - bg = bgtag['data'][1] - else: - bg = None - - if string[0] in DEC_DIGITS: - if string[1] in DEC_DIGITS: - fg = get_mirc_color(string[:2]) - string = string[1:] - color_chars += 2 - - else: - fg = get_mirc_color(string[0]) - color_chars += 1 - - if string[1] == "," and string[2] in DEC_DIGITS: - if string[3] in DEC_DIGITS: - bg = get_mirc_color(string[2:4]) - color_chars += 3 - - else: - bg = get_mirc_color(string[2]) - color_chars += 2 - - else: - fg = bg = None - - if fg: - open_tags[MIRC_COLOR] = {'data': ("foreground",fg), 'from': pos} - else: - open_tags.pop(MIRC_COLOR,None) - - if bg: - open_tags[MIRC_COLOR_BG] = {'data': ("background",bg), 'from': pos} - else: - open_tags.pop(MIRC_COLOR_BG,None) - - return color_chars - -def parse_bersirc_color(string, pos, open_tags, tags): - bg = None - if MIRC_COLOR in open_tags: - tag = open_tags.pop(MIRC_COLOR) - tag['to'] = pos - tags.append(tag) - - if MIRC_COLOR_BG in open_tags: - bgtag = open_tags.pop(MIRC_COLOR_BG) - bgtag['to'] = pos - tags.append(bgtag) - - bg = bgtag['data'][1] - - for c in (0, 1, 2, 3, 4, 5): - if string[c] not in HEX_DIGITS: - return 1 - fg = '#' + string[:6].upper() - - color_chars = 7 - for c in (7, 8, 9, 10, 11, 12): - if string[c] not in HEX_DIGITS: - break - else: - if string[6] == ",": - bg = '#' + string[7:13].upper() - color_chars = 14 - - if fg: - open_tags[MIRC_COLOR] = {'data': ("foreground",fg), 'from': pos} - else: - open_tags.pop(MIRC_COLOR,None) - - if bg: - open_tags[MIRC_COLOR_BG] = {'data': ("background",bg), 'from': pos} - else: - open_tags.pop(MIRC_COLOR_BG,None) - - return color_chars - -def parse_bold(string, pos, open_tags, tags): - if BOLD in open_tags: - tag = open_tags.pop(BOLD) - tag['to'] = pos - tags.append(tag) - - else: - open_tags[BOLD] = {'data': ('weight', BOLD), 'from': pos} - - return 1 - -def parse_underline(string, pos, open_tags, tags): - if UNDERLINE in open_tags: - tag = open_tags.pop(UNDERLINE) - tag['to'] = pos - tags.append(tag) - - else: - open_tags[UNDERLINE] = {'data': ('underline', UNDERLINE), 'from': pos} - - return 1 - -def parse_reset(string, pos, open_tags, tags): - for t in open_tags: - tag = open_tags[t] - tag['to'] = pos - tags.append(tag) - - open_tags.clear() - - return 1 - -tag_parser = { - MIRC_COLOR: parse_mirc_color, - BERS_COLOR: parse_bersirc_color, - BOLD: parse_bold, - UNDERLINE: parse_underline, - RESET: parse_reset - } - -def parse_mirc(string): - string += RESET - - out = '' - open_tags = {} - tags = [] - text_i = outtext_i = 0 - - for tag_i, char in enumerate(string): - if char in tag_parser: - out += string[text_i:tag_i] - - outtext_i += tag_i - text_i - - text_i = tag_i + tag_parser[char]( - string[tag_i+1:], - outtext_i, - open_tags, - tags - ) - - return tags, out - -#transforms for unparse_mirc - -#^O -def transform_reset(start, end): - return RESET, '', {} - -#^K -def transform_color_reset(start, end): - if ('foreground' in start and 'foreground' not in end) or \ - ('background' in start and 'background' not in end): - result = start.copy() - result.pop("foreground",None) - result.pop("background",None) - return MIRC_COLOR, DEC_DIGITS, result - else: - return '','',start - -#^KXX -def transform_color(start, end): - if (start.get('foreground',99) != end.get('foreground',99)): - confcolors = conf.get('colors', colors) - result = start.copy() - if 'foreground' in end: - try: - index = list(confcolors).index(end['foreground'].upper()) - except ValueError: - return '','',start - result['foreground'] = end['foreground'] - else: - index = 99 - del result['foreground'] - return '\x03%02i' % index, ',', result - else: - return '','',start - -#^KXX,YY -def transform_bcolor(start, end): - if (start.get('background',99) != end.get('background',99)): - confcolors = conf.get('colors', colors) - result = start.copy() - if 'foreground' in end: - try: - fg_index = list(confcolors).index(end['foreground'].upper()) - except ValueError: - return '','',start - result['foreground'] = end['foreground'] - else: - fg_index = 99 - result.pop('foreground',None) - if 'background' in end: - try: - bg_index = list(confcolors).index(end['background'].upper()) - except ValueError: - return '','',start - result['background'] = end['background'] - else: - bg_index = 99 - del result['background'] - return '\x03%02i,%02i' % (fg_index, bg_index), ',', result - else: - return '','',start - -#^LXXXXXX -def transform_bersirc(start, end): - if 'foreground' in end and end['foreground'] != start.get('foreground'): - result = start.copy() - result['foreground'] = end['foreground'] - return "\x04%s" % end['foreground'][1:], ',', result - else: - return '','',start - -#^LXXXXXX,YYYYYY -def transform_bbersirc(start, end): - if 'foreground' in end and 'background' in end and ( - end['foreground'] != start.get('foreground') or - end['background'] != start.get('background')): - result = start.copy() - result['foreground'] = end['foreground'] - result['background'] = end['background'] - return "\x04%s,%s" % (end['foreground'][1:], end['background'][1:]), ',', result - else: - return '','',start - - -#^B -def transform_underline(start, end): - if ('underline' in start) != ('underline' in end): - result = start.copy() - if 'underline' in start: - del result['underline'] - else: - result['underline'] = UNDERLINE - return UNDERLINE, '', result - else: - return '','',start - -#^U -def transform_bold(start, end): - if ('weight' in start) != ('weight' in end): - result = start.copy() - if 'weight' in start: - del result['weight'] - else: - result['weight'] = BOLD - return BOLD, '', result - else: - return '','',start - -#^B^B -#In some rare circumstances, we HAVE to do this to generate a working string -def transform_dbold(start, end): - return BOLD*2, '', start - -#return the formatting needed to transform one set of format tags to another -def transform(start, end, nextchar=" "): - transform_functions = ( - transform_reset, transform_color_reset, transform_color, transform_bcolor, - transform_bersirc, transform_bbersirc, transform_underline, - transform_bold, transform_dbold, - ) - - candidates = [('','',start)] - result = None - - for f in transform_functions: - for string, badchars, s in candidates[:]: - newstring, badchars, s = f(s, end) - string += newstring - if newstring and (result == None or len(string) < len(result)): - if nextchar not in badchars and s == end: - result = string - else: - candidates.append((string, badchars, s)) - return result - -def unparse_mirc(tagsandtext): - lasttags, lastchar = {}, '' - - string = [] - for tags, char in tagsandtext: - if tags != lasttags: - string.append(transform(lasttags, tags, char[0])) - string.append(char) - lasttags, lastchar = tags, char - return ''.join(string) - -if __name__ == "__main__": - tests = [ - 'not\x02bold\x02not', - 'not\x1Funderline\x1Fnot', - - "\x02\x1FHi\x0F", - - 'not\x030,17white-on-black\x0304red-on-black\x03nothing', - - "\x040000CC<\x04nick\x040000CC>\x04 text", - - '\x04770077,FFFFFFbersirc color with background! \x04000077setting foreground! \x04reset!', - - '\x047700,FFFFbersirc', - - "\x03123Hello", - - "\x0312,Hello", - - "\x034Hello", - - "Bo\x02ld", - - "\x034,5Hello\x036Goodbye", - - "\x04ff0000,00ff00Hello\x040000ffGoodbye", - - "\x04777777(\x0400CCCCstuff\x04777777)\x04", - - '\x0307orange\x04CCCCCCgrey\x0307orange', - - '\x04CCCCCC,444444sdf\x0304jkl', - - '\x0403\x02\x02,trixy', - - '\x04FFFFFF\x02\x02,000000trixy for bersirc', - ] - - results = [ - ([{'from': 3, 'data': ('weight', '\x02'), 'to': 7}], 'notboldnot'), - - ([{'from': 3, 'data': ('underline', '\x1f'), 'to': 12}], 'notunderlinenot'), - - ([{'from': 0, 'data': ('weight', '\x02'), 'to': 2}, {'from': 0, 'data': ('underline', '\x1f'), 'to': 2}], 'Hi'), - - ([{'from': 3, 'data': ('foreground', '#FFFFFF'), 'to': 17}, {'from': 3, 'data': ('background', '#000000'), 'to': 17}, {'from': 17, 'data': ('foreground', '#FF0000'), 'to': 29}, {'from': 17, 'data': ('background', '#000000'), 'to': 29}], 'notwhite-on-blackred-on-blacknothing'), - - ([{'from': 0, 'data': ('foreground', '#0000CC'), 'to': 1}, {'from': 5, 'data': ('foreground', '#0000CC'), 'to': 6}], ' text'), - - ([{'from': 0, 'data': ('foreground', '#770077'), 'to': 31}, {'from': 0, 'data': ('background', '#FFFFFF'), 'to': 31}, {'from': 31, 'data': ('foreground', '#000077'), 'to': 51}, {'from': 31, 'data': ('background', '#FFFFFF'), 'to': 51}], 'bersirc color with background! setting foreground! reset!'), - - ([], '7700,FFFFbersirc'), - - ([{'from': 0, 'data': ('foreground', '#0000FF'), 'to': 6}], '3Hello'), - - ([{'from': 0, 'data': ('foreground', '#0000FF'), 'to': 6}], ',Hello'), - - ([{'from': 0, 'data': ('foreground', '#FF0000'), 'to': 5}], 'Hello'), - - ([{'from': 2, 'data': ('weight', '\x02'), 'to': 4}], 'Bold'), - - ([{'from': 0, 'data': ('foreground', '#FF0000'), 'to': 5}, {'from': 0, 'data': ('background', '#7F0000'), 'to': 5}, {'from': 5, 'data': ('foreground', '#9C009C'), 'to': 12}, {'from': 5, 'data': ('background', '#7F0000'), 'to': 12}], 'HelloGoodbye'), - - ([{'from': 0, 'data': ('foreground', '#FF0000'), 'to': 5}, {'from': 0, 'data': ('background', '#00FF00'), 'to': 5}, {'from': 5, 'data': ('foreground', '#0000FF'), 'to': 12}, {'from': 5, 'data': ('background', '#00FF00'), 'to': 12}], 'HelloGoodbye'), - - ([{'from': 0, 'data': ('foreground', '#777777'), 'to': 1}, {'from': 1, 'data': ('foreground', '#00CCCC'), 'to': 6}, {'from': 6, 'data': ('foreground', '#777777'), 'to': 7}], '(stuff)'), - - ([{'from': 0, 'data': ('foreground', '#FF7F00'), 'to': 6}, {'from': 6, 'data': ('foreground', '#CCCCCC'), 'to': 10}, {'from': 10, 'data': ('foreground', '#FF7F00'), 'to': 16}], 'orangegreyorange'), - - ([{'from': 0, 'data': ('foreground', '#CCCCCC'), 'to': 3}, {'from': 0, 'data': ('background', '#444444'), 'to': 3}, {'from': 3, 'data': ('foreground', '#FF0000'), 'to': 6}, {'from': 3, 'data': ('background', '#444444'), 'to': 6}], 'sdfjkl'), - - ([{'from': 2, 'data': ('weight', '\x02'), 'to': 2}], '03,trixy'), - - ([{'from': 0, 'data': ('weight', '\x02'), 'to': 0}, {'from': 0, 'data': ('foreground', '#FFFFFF'), 'to': 24}], ',000000trixy for bersirc'), - ] - - #""" - - #r = range(20000) - #for i in r: - # for test in tests: - # parse_mirc(test) - - """ - - lines = [eval(line.strip()) for line in file("parse_mirc_torture_test.txt")] - - for r in range(100): - for line in lines: - parse_mirc(line) - - #""" - - def setify_tags(tags): - return set(frozenset(tag.iteritems()) for tag in tags if tag['from'] != tag['to']) - - def parsed_eq((tags1, text1), (tags2, text2)): - return setify_tags(tags1) == setify_tags(tags2) and text1 == text2 - - def parsed_to_unparsed((tags, text)): - result = [] - for i, char in enumerate(text): - result.append(( - dict(tag['data'] for tag in tags if tag['from'] <= i < tag['to']), - char)) - return result - - for i, (test, result) in enumerate(zip(tests, results)): - if not parsed_eq(parse_mirc(test), result): - print "parse_mirc failed test %s:" % i - print repr(test) - print parse_mirc(test) - print result - print - - elif not parsed_eq(parse_mirc(unparse_mirc(parsed_to_unparsed(result))), result): - print "unparse_mirc failed test %s:" % i - print repr(test) - print unparse_mirc(test) - print - -#import dis -#dis.dis(parse_mirc) diff --git a/services/console/lib/purk/scripts/Makefile.am b/services/console/lib/purk/scripts/Makefile.am deleted file mode 100644 index 00ffbf8b..00000000 --- a/services/console/lib/purk/scripts/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -sugardir = $(pkgdatadir)/services/console/lib/purk/scripts - -sugar_PYTHON = \ - alias.py \ - chaninfo.py \ - clicks.py \ - completion.py \ - console.py \ - history.py \ - ignore.py \ - irc_script.py \ - keys.py \ - theme.py \ - timeout.py \ - ui_script.py - diff --git a/services/console/lib/purk/scripts/alias.py b/services/console/lib/purk/scripts/alias.py deleted file mode 100755 index ffd213d8..00000000 --- a/services/console/lib/purk/scripts/alias.py +++ /dev/null @@ -1,60 +0,0 @@ -import sys -import os - -from conf import conf - -aliases = conf.get("aliases",{ - 'op':'"mode "+window.id+" +"+"o"*len(args)+" "+" ".join(args)', - 'deop':'"mode "+window.id+" -"+"o"*len(args)+" "+" ".join(args)', - 'voice':'"mode "+window.id+" +"+"v"*len(args)+" "+" ".join(args)', - 'devoice':'"mode "+window.id+" -"+"v"*len(args)+" "+" ".join(args)', - 'umode':'"mode "+network.me+" "+" ".join(args)', - 'clear':'window.output.clear()', - }) - -class CommandHandler: - __slots__ = ["command"] - def __init__(self, command): - self.command = command - def __call__(self, e): - loc = sys.modules.copy() - loc.update(e.__dict__) - result = eval(self.command,loc) - if isinstance(result,basestring): - core.events.run(result,e.window,e.network) - -for name in aliases: - globals()['onCommand'+name.capitalize()] = CommandHandler(aliases[name]) - -def onCommandAlias(e): - if e.args and 'r' in e.switches: - name = e.args[0].lower() - command = aliases[name] - del aliases[name] - conf['aliases'] = aliases - e.window.write("* Deleted alias %s%s (was %s)" % (conf.get('command-prefix','/'),name,command)) - core.events.load(__name__,reloading=True) - elif 'l' in e.switches: - e.window.write("* Current aliases:") - for i in aliases: - e.window.write("* %s%s: %s" % (conf.get('command-prefix','/'),i,aliases[i])) - elif len(e.args) >= 2: - name = e.args[0].lower() - command = ' '.join(e.args[1:]) - aliases[name] = command - conf['aliases'] = aliases - e.window.write("* Created an alias %s%s to %s" % (conf.get('command-prefix','/'),name,command)) - core.events.reload(__name__) - elif len(e.args) == 1: - name = e.args[0].lower() - if name in aliases: - e.window.write("* %s%s is an alias to %s" % (conf.get('command-prefix','/'),name,aliases[name])) - else: - e.window.write("* There is no alias %s%s" % (conf.get('command-prefix','/'),name)) - else: - e.window.write( -"""Usage: - /alias \x02name\x02 \x02expression\x02 to create or replace an alias - /alias \x02name\x02 to look at an alias - /alias -r \x02name\x02 to remove an alias - /alias -l to see a list of aliases""") diff --git a/services/console/lib/purk/scripts/chaninfo.py b/services/console/lib/purk/scripts/chaninfo.py deleted file mode 100644 index e6ff3a0e..00000000 --- a/services/console/lib/purk/scripts/chaninfo.py +++ /dev/null @@ -1,320 +0,0 @@ -import windows - -def _justprefix(network, channel, nick): - fr, to = network.isupport["PREFIX"][1:].split(")") - - for mode, prefix in zip(fr, to): - if mode in channel.nicks.get(nick, ''): - return prefix - - return '' - -def prefix(network, channelname, nick): - channel = getchan(network, channelname) - - if channel: - nick = '%s%s' % (_justprefix(network, channel, nick), nick) - - return nick - -def escape(string): - for escapes in (('&','&'), ('<','<'), ('>','>')): - string = string.replace(*escapes) - return string - -def sortkey(network, channelname, nick): - chanmodes, dummy = network.isupport["PREFIX"][1:].split(")") - nickmodes = mode(network, channelname, nick) - - return '%s%s' % (''.join(str(int(mode not in nickmodes)) for mode in chanmodes), network.norm_case(nick)) - -def nicklist_add(network, channel, nick): - window = windows.get(windows.ChannelWindow, network, channel.name, core) - #window = core.window - if window: - window.nicklist.append(nick, escape(prefix(network, channel.name, nick)), sortkey(network, channel.name, nick)) - -def nicklist_del(network, channel, nick): - window = windows.get(windows.ChannelWindow, network, channel.name, core) - #window = core.window - if window: - try: - window.nicklist.remove(nick) - except ValueError: - pass - -def setupListRightClick(e): - if isinstance(e.window, windows.ChannelWindow): - #if isinstance(core.window, windows.ChannelWindow): - #if e.data[0] in e.window.network.isupport["PREFIX"].split(")")[1]: - if e.data[0] in core.window.network.isupport["PREFIX"].split(")")[1]: - e.nick = e.data[1:] - else: - e.nick = e.data - -def setupSocketConnect(e): - e.network.channels = {} - -def setdownDisconnect(e): - e.network.channels = {} - -class Channel(object): - def __init__(self, name): - self.name = name - self.nicks = {} - self.normal_nicks = {} # mapping of normal nicks to actual nicks - self.getting_names = False #are we between lines in a /names reply? - self.mode = '' - self.special_mode = {} #for limits, keys, and anything similar - self.topic = '' - self.got_mode = False #did we get at least one mode reply? - self.got_names = False #did we get at least one names reply? - -def getchan(network, channel): - return hasattr(network, 'channels') and network.channels.get(network.norm_case(channel)) - -#return a list of channels you're on on the given network -def channels(network): - if not hasattr(network, 'channels'): - network.channels = {} - - return list(network.channels) - -#return True if you're on the channel -def ischan(network, channel): - return bool(getchan(network, channel)) - -#return True if the nick is on the channel -def ison(network, channel, nickname): - channel = getchan(network, channel) - return channel and network.norm_case(nickname) in channel.normal_nicks - -#return a list of nicks on the given channel -def nicks(network, channel): - channel = getchan(network, channel) - - if channel: - return channel.nicks - else: - return {} - -#return the mode on the given channel -def mode(network, channel, nickname=''): - channel = getchan(network, channel) - - if channel: - if nickname: - realnick = channel.normal_nicks.get(network.norm_case(nickname)) - if realnick: - return channel.nicks[realnick] - - else: - result = channel.mode - for m in channel.mode: - if m in channel.special_mode: - result += ' '+channel.special_mode[m] - return result - - return '' - -#return the topic on the given channel -def topic(network, channel): - channel = getchan(network, channel) - - if channel: - return channel.topic - else: - return '' - -def setupJoin(e): - print e - if e.source == e.network.me: - e.network.channels[e.network.norm_case(e.target)] = Channel(e.target) - e.network.raw('MODE '+e.target) - - #if we wanted to be paranoid, we'd account for not being on the channel - channel = getchan(e.network,e.target) - channel.nicks[e.source] = '' - channel.normal_nicks[e.network.norm_case(e.source)] = e.source - - if e.source == e.network.me: - #If the channel window already existed, and we're joining, then we - #didn't clear out the nicklist when we left. That means we have to clear - #it out now. - window = windows.get(windows.ChannelWindow, e.network, e.target, core) - #window = core.window - #print core - if window: - window.nicklist.clear() - - nicklist_add(e.network, channel, e.source) - -def setdownPart(e): - if e.source == e.network.me: - del e.network.channels[e.network.norm_case(e.target)] - else: - channel = getchan(e.network,e.target) - nicklist_del(e.network, channel, e.source) - del channel.nicks[e.source] - del channel.normal_nicks[e.network.norm_case(e.source)] - -def setdownKick(e): - if e.target == e.network.me: - del e.network.channels[e.network.norm_case(e.channel)] - else: - channel = getchan(e.network,e.channel) - nicklist_del(e.network, channel, e.target) - del channel.nicks[e.target] - del channel.normal_nicks[e.network.norm_case(e.target)] - -def setdownQuit(e): - #if paranoid: check if e.source is me - for channame in channels(e.network): - channel = getchan(e.network,channame) - if e.source in channel.nicks: - nicklist_del(e.network, channel, e.source) - del channel.nicks[e.source] - del channel.normal_nicks[e.network.norm_case(e.source)] - -def setupMode(e): - channel = getchan(e.network,e.channel) - if channel: - user_modes = e.network.isupport['PREFIX'].split(')')[0][1:] - - (list_modes, - always_parm_modes, - set_parm_modes, - normal_modes) = e.network.isupport['CHANMODES'].split(',') - - list_modes += user_modes - - mode_on = True #are we reading a + section or a - section? - params = e.text.split(' ') - - for char in params.pop(0): - if char == '+': - mode_on = True - - elif char == '-': - mode_on = False - - else: - if char in user_modes: - #these are modes like op and voice - nickname = params.pop(0) - nicklist_del(e.network, channel, nickname) - if mode_on: - channel.nicks[nickname] += char - else: - channel.nicks[nickname] = channel.nicks[nickname].replace(char, '') - nicklist_add(e.network, channel, nickname) - - elif char in list_modes: - #things like ban/unban - #FIXME: We don't keep track of those lists here, but we know - # when they're changed and how. Scriptors should be able to - # take advantage of this - params.pop(0) - - elif char in always_parm_modes: - #these always have a parameter - param = params.pop(0) - - if mode_on: - channel.special_mode[char] = param - else: - #account for unsetting modes that aren't set - channel.special_mode.pop(char, None) - - elif char in set_parm_modes: - #these have a parameter only if they're being set - if mode_on: - channel.special_mode[char] = params.pop(0) - else: - #account for unsetting modes that aren't set - channel.special_mode.pop(char, None) - - if char not in list_modes: - if mode_on: - channel.mode = channel.mode.replace(char, '')+char - else: - channel.mode = channel.mode.replace(char, '') - -def setdownNick(e): - for channame in channels(e.network): - channel = getchan(e.network,channame) - if e.source in channel.nicks: - nicklist_del(e.network, channel, e.source) - del channel.normal_nicks[e.network.norm_case(e.source)] - channel.nicks[e.target] = channel.nicks[e.source] - del channel.nicks[e.source] - channel.normal_nicks[e.network.norm_case(e.target)] = e.target - nicklist_add(e.network, channel, e.target) - -def setupTopic(e): - channel = getchan(e.network, e.target) - if channel: - channel.topic = e.text - -def setupRaw(e): - if e.msg[1] == '353': #names reply - channel = getchan(e.network,e.msg[4]) - if channel: - if not channel.getting_names: - channel.nicks.clear() - channel.normal_nicks.clear() - channel.getting_names = True - if not channel.got_names: - e.quiet = True - for nickname in e.msg[5].split(' '): - if nickname: - if not nickname[0].isalpha() and nickname[0] in e.network.prefixes: - n = nickname[1:] - channel.nicks[n] = e.network.prefixes[nickname[0]] - channel.normal_nicks[e.network.norm_case(n)] = n - else: - channel.nicks[nickname] = '' - channel.normal_nicks[e.network.norm_case(nickname)] = nickname - - elif e.msg[1] == '366': #end of names reply - channel = getchan(e.network,e.msg[3]) - if channel: - if not channel.got_names: - e.quiet = True - channel.got_names = True - channel.getting_names = False - - window = windows.get(windows.ChannelWindow, e.network, e.msg[3], core) - if window: - window.nicklist.replace( - (nick, escape(prefix(e.network, channel.name, nick)), sortkey(e.network, channel.name, nick)) for nick in channel.nicks - ) - - elif e.msg[1] == '324': #channel mode is - channel = getchan(e.network,e.msg[3]) - if channel: - if not channel.got_mode: - e.quiet = True - channel.got_mode = True - mode = e.msg[4] - params = e.msg[:4:-1] - list_modes, always_parm_modes, set_parm_modes, normal_modes = \ - e.network.isupport['CHANMODES'].split(',') - parm_modes = always_parm_modes + set_parm_modes - channel.mode = e.msg[4] - channel.special_mode.clear() - for char in channel.mode: - if char in parm_modes: - channel.special_mode[char] = params.pop() - - elif e.msg[1] == '331': #no topic - channel = getchan(e.network,e.msg[3]) - if channel: - channel.topic = '' - - elif e.msg[1] == '332': #channel topic is - channel = getchan(e.network,e.msg[3]) - if channel: - channel.topic = e.text - -#core.events.load(__name__) diff --git a/services/console/lib/purk/scripts/clicks.py b/services/console/lib/purk/scripts/clicks.py deleted file mode 100644 index b2f3f829..00000000 --- a/services/console/lib/purk/scripts/clicks.py +++ /dev/null @@ -1,146 +0,0 @@ -import ui -import windows -import chaninfo -from conf import conf - -def set_target(e): - target_l = e.target.lstrip('@+%.(<') - e._target_fr = e.target_fr + len(e.target) - len(target_l) - - target_r = e.target.rstrip('>:,') - e._target_to = e.target_to - len(e.target) + len(target_r) - - if target_r.endswith(')'): - e._target = e.text[e._target_fr:e._target_to] - open_parens = e._target.count('(') - e._target.count(')') - while open_parens < 0 and e.text[e._target_to-1] == ')': - e._target_to -= 1 - open_parens += 1 - - e._target = e.text[e._target_fr:e._target_to] - -def is_nick(e): - return isinstance(e.window, windows.ChannelWindow) and \ - chaninfo.ison(e.window.network, e.window.id, e._target) - -def is_url(e): - def starts(prefix, mindots=1): - def prefix_url(target): - return target.startswith(prefix) and target.count('.') >= mindots - - return prefix_url - - to_check = [starts(*x) for x in [ - ('http://', 1), - ('https://', 1), - ('ftp://', 1), - ('www', 2), - ]] - - for check_url in to_check: - if check_url(e._target): - return True - - return False - -def is_chan(e): - # click on a #channel - return e.window.network and e._target and \ - e._target[0] in e.window.network.isupport.get('CHANTYPES', '&#$+') - -def get_autojoin_list(network): - perform = conf.get('networks',{}).get(network.name,{}).get('perform',()) - channels = set() - for line in perform: - if line.startswith('join ') and ' ' not in line[5:]: - channels.update(line[5:].split(',')) - return channels - -def add_autojoin(network, channel): - if 'networks' not in conf: - conf['networks'] = {} - if network.name not in conf['networks']: - conf['networks'][network.name] = {'server': network.server} - conf['start_networks'] = conf.get('start_networks',[]) + [network.name] - if 'perform' in conf['networks'][network.name]: - perform = conf['networks'][network.name]['perform'] - else: - perform = conf['networks'][network.name]['perform'] = [] - - for n, line in enumerate(perform): - if line.startswith('join ') and ' ' not in line[5:]: - perform[n] = "%s,%s" % (line, channel) - break - else: - perform.append('join %s' % channel) - -def make_nick_menu(e, target): - def query(): - core.events.run('query %s' % target, e.window, e.window.network) - - def whois(): - core.events.run('whois %s' % target, e.window, e.window.network) - - e.menu += [ - ('Query', query), - ('Whois', whois), - (), - ] - -def onHover(e): - set_target(e) - - for is_check in (is_nick, is_url, is_chan): - if is_check(e): - e.tolink.add((e._target_fr, e._target_to)) - break - -def onClick(e): - set_target(e) - - if is_nick(e): - core.events.run('query %s' % e._target, e.window, e.window.network) - - # url of the form http://xxx.xxx or www.xxx.xxx - elif is_url(e): - if e._target.startswith('www'): - e._target = 'http://%s' % e._target - ui.open_file(e._target) - - # click on a #channel - elif is_chan(e): - if not chaninfo.ischan(e.window.network, e._target): - e.window.network.join(e._target) - window = windows.get(windows.ChannelWindow, e.window.network, e._target) - if window: - window.activate() - -def onRightClick(e): - set_target(e) - - # nick on this channel - if is_nick(e): - make_nick_menu(e, e._target) - - elif is_url(e): - if e._target.startswith('www'): - e._target = 'http://%s' % e._target - - def copy_to(): - # copy to clipboard - ui.set_clipboard(e._target) - - e.menu += [('Copy', copy_to)] - - elif is_chan(e): - e.channel = e._target - e.network = e.window.network - core.events.trigger('ChannelMenu', e) - -def onListRightClick(e): - if isinstance(e.window, windows.ChannelWindow): - make_nick_menu(e, e.nick) - -def onListDoubleClick(e): - if isinstance(e.window, windows.ChannelWindow): - core.events.run("query %s" % e.target, e.window, e.window.network) diff --git a/services/console/lib/purk/scripts/completion.py b/services/console/lib/purk/scripts/completion.py deleted file mode 100644 index 1719702c..00000000 --- a/services/console/lib/purk/scripts/completion.py +++ /dev/null @@ -1,135 +0,0 @@ -import windows -import chaninfo -from conf import conf - -def channel_completer(window, left, right, text): - if isinstance(window, windows.ChannelWindow): - yield window.id - - for w in windows.get_with(wclass=windows.ChannelWindow, network=window.network): - if w is not window: - yield w.id - - for w in windows.get_with(wclass=windows.ChannelWindow): - if w.network is not window.network: - yield w.id - -# normal server commands -srv_commands = ('ping', 'join', 'part', 'mode', 'server', 'kick', - 'quit', 'nick', 'privmsg', 'notice', 'topic') - -def command_completer(window, left, right, text): - for c in srv_commands: - yield '/%s' % c - - if 'CMDS' in window.network.isupport: - for c in window.network.isupport['CMDS'].split(','): - yield '/%s' % c.lower() - - for c in core.events.all_events: - if c.startswith('Command') and c != 'Command': - yield '/%s' % c[7:].lower() - -def nick_completer(window, left, right, text): - if type(window) == windows.QueryWindow: - yield window.id - - recent_speakers = getattr(window, 'recent_speakers', ()) - - for nick in recent_speakers: - if chaninfo.ison(window.network, window.id, nick): - yield nick - - for nick in chaninfo.nicks(window.network, window.id): - if nick not in recent_speakers: - yield nick - -def script_completer(window, left, right, text): - return core.events.loaded.iterkeys() - -def network_completer(window, left, right, text): - return conf.get('networks', {}).iterkeys() - -def get_completer_for(window): - input = window.input - - left, right = input.text[:input.cursor], input.text[input.cursor:] - - text = left.split(' ')[-1] - - while True: - suffix = '' - if text and text[0] in window.network.isupport.get('CHANTYPES', '#&+'): - candidates = channel_completer(window, left, right, text) - - elif input.text.startswith('/reload '): - candidates = script_completer(window, left, right, text) - - elif input.text.startswith('/edit '): - candidates = script_completer(window, left, right, text) - - elif input.text.startswith('/server '): - candidates = network_completer(window, left, right, text) - - elif text.startswith('/'): - candidates = command_completer(window, left, right, text) - suffix = ' ' - - else: - candidates = nick_completer(window, left, right, text) - - if left == text: - suffix = ': ' - else: - suffix = ' ' - - if text: - before = left[:-len(text)] - else: - before = left - - insert_text = '%s%s%s%s' % (before, '%s', suffix, right) - cursor_pos = len(before + suffix) - - original = window.input.text, window.input.cursor - - for cand in candidates: - if cand.lower().startswith(text.lower()): - window.input.text, window.input.cursor = insert_text % cand, cursor_pos + len(cand) - yield None - - window.input.text, window.input.cursor = original - yield None - -# generator--use recent_completer.next() to continue cycling through whatever -recent_completer = None - -def onKeyPress(e): - global recent_completer - - if e.key == 'Tab': - if not recent_completer: - recent_completer = get_completer_for(e.window) - - recent_completer.next() - - else: - recent_completer = None - -def onActive(e): - global recent_completer - - recent_completer = None - -def onText(e): - if chaninfo.ischan(e.network, e.target): - if not hasattr(e.window, 'recent_speakers'): - e.window.recent_speakers = [] - - for nick in e.window.recent_speakers: - if nick == e.source or not chaninfo.ison(e.network, e.target, nick): - e.window.recent_speakers.remove(nick) - - e.window.recent_speakers.insert(0, e.source) - -onAction = onText diff --git a/services/console/lib/purk/scripts/console.py b/services/console/lib/purk/scripts/console.py deleted file mode 100755 index bef8e0e6..00000000 --- a/services/console/lib/purk/scripts/console.py +++ /dev/null @@ -1,68 +0,0 @@ -import sys -import traceback -import windows -from conf import conf - -class ConsoleWriter: - __slots__ = ['window'] - def __init__(self, window): - self.window = window - def write(self, text): - try: - self.window.write(text, line_ending='') - except: - self.window.write(traceback.format_exc()) - -class ConsoleWindow(windows.SimpleWindow): - def __init__(self, network, id): - windows.SimpleWindow.__init__(self, network, id) - - writer = ConsoleWriter(self) - - sys.stdout = writer - sys.stderr = writer - - self.globals = {'window': self} - self.locals = {} - -#this prevents problems (and updates an open console window) on reload -#window = None -#for window in manager: -# if type(window).__name__ == "ConsoleWindow": -# window.mutate(ConsoleWindow, window.network, window.id) -#del window - -def onClose(e): - if isinstance(e.window, ConsoleWindow): - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - -def onCommandConsole(e): - windows.new(ConsoleWindow, None, "console").activate() - -def onCommandSay(e): - if isinstance(e.window, ConsoleWindow): - import pydoc #fix nonresponsive help() command - old_pager, pydoc.pager = pydoc.pager, pydoc.plainpager - e.window.globals.update(sys.modules) - text = ' '.join(e.args) - try: - e.window.write(">>> %s" % text) - result = eval(text, e.window.globals, e.window.locals) - if result is not None: - e.window.write(repr(result)) - e.window.globals['_'] = result - except SyntaxError: - try: - exec text in e.window.globals, e.window.locals - except: - traceback.print_exc() - except: - traceback.print_exc() - pydoc.pager = old_pager - else: - raise core.events.CommandError("There's no one here to speak to.") - -def onStart(e): - if conf.get('start-console'): - windows.new(ConsoleWindow, None, "console") diff --git a/services/console/lib/purk/scripts/history.py b/services/console/lib/purk/scripts/history.py deleted file mode 100644 index 379ad5e3..00000000 --- a/services/console/lib/purk/scripts/history.py +++ /dev/null @@ -1,45 +0,0 @@ -def onKeyPress(e): - if not hasattr(e.window, 'history'): - e.window.history = [], -1 - - if e.key in ('Up', 'Down'): - h, i = e.window.history - - if i == -1 and e.window.input.text: - h.insert(0, e.window.input.text) - i = 0 - - if e.key == 'Up': - i += 1 - - if i < len(h): - e.window.history = h, i - - e.window.input.text = h[i] - e.window.input.cursor = -1 - - else: # e.key == 'Up' - i -= 1 - - if i > -1: - e.window.history = h, i - - e.window.input.text = h[i] - e.window.input.cursor = -1 - - elif i == -1: - e.window.history = h, i - - e.window.input.text = '' - e.window.input.cursor = -1 - -def onInput(e): - if not hasattr(e.window, 'history'): - e.window.history = [], -1 - - if e.text: - h, i = e.window.history - - h.insert(0, e.text) - - e.window.history = h, -1 diff --git a/services/console/lib/purk/scripts/ignore.py b/services/console/lib/purk/scripts/ignore.py deleted file mode 100755 index 98b4eed6..00000000 --- a/services/console/lib/purk/scripts/ignore.py +++ /dev/null @@ -1,43 +0,0 @@ -from conf import conf -import irc - -def preRaw(e): - if e.msg[1] in ('PRIVMSG','NOTICE'): - address = e.network.norm_case('%s!%s' % (e.source, e.address)) - for mask in conf.get('ignore_masks',()): - if irc.match_glob(address, e.network.norm_case(mask)): - core.events.halt() - -def onCommandIgnore(e): - if 'ignore_masks' not in conf: - conf['ignore_masks'] = [] - if 'l' in e.switches: - for i in conf['ignore_masks']: - e.window.write('* %s' % i) - elif 'c' in e.switches: - del conf['ignore_masks'] - e.window.write('* Cleared the ignore list.') - elif e.args: - if '!' in e.args[0] or '*' in e.args[0] or '?' in e.args[0]: - mask = e.args[0] - else: - mask = '%s!*' % e.args[0] - if 'r' in e.switches: - if mask in conf['ignore_masks']: - conf['ignore_masks'].remove(mask) - e.window.write('* Removed %s from the ignore list' % e.args[0]) - else: - raise core.events.CommandError("Couldn't find %s in the ignore list" % e.args[0]) - else: - if mask in conf['ignore_masks']: - e.window.write('* %s is already ignored' % e.args[0]) - else: - conf['ignore_masks'].append(mask) - e.window.write('* Ignoring messages from %s' % e.args[0]) - else: - e.window.write( -"""Usage: - /ignore \x02nick/mask\x02 to ignore a nickname or mask - /ignore -r \x02nick/mask\x02 to stop ignoring a nickname or mask - /ignore -l to view the ignore list - /ignore -c to clear the ignore list""") diff --git a/services/console/lib/purk/scripts/irc_script.py b/services/console/lib/purk/scripts/irc_script.py deleted file mode 100644 index 4582d725..00000000 --- a/services/console/lib/purk/scripts/irc_script.py +++ /dev/null @@ -1,588 +0,0 @@ -import time - -from conf import conf -import ui -import windows -import irc - -COMMAND_PREFIX = conf.get('command_prefix', '/') - -NICK_SUFFIX = r"`_-\|0123456789" - -_hextochr = dict(('%02x' % i, chr(i)) for i in range(256)) -def unquote(url, rurl=""): - - while '%' in url: - url, char = url.rsplit('%', 1) - - chars = char[:2].lower() - - if chars in _hextochr: - rurl = '%s%s%s' % (_hextochr[chars], char[2:], rurl) - else: - rurl = "%s%s%s" % ('%', char, rurl) - - return url + rurl - -#for getting a list of alternative nicks to try on a network -def _nick_generator(network): - for nick in network.nicks[1:]: - yield nick - if network._nick_error: - nick = 'ircperson' - else: - nick = network.nicks[0] - import itertools - for i in itertools.count(1): - for j in xrange(len(NICK_SUFFIX)**i): - suffix = ''.join(NICK_SUFFIX[(j/(len(NICK_SUFFIX)**x))%len(NICK_SUFFIX)] for x in xrange(i)) - if network._nick_max_length: - yield nick[0:network._nick_max_length-i]+suffix - else: - yield nick+suffix - -def setdownRaw(e): - if not e.done: - if not e.network.got_nick: - if e.msg[1] in ('432','433','436','437'): #nickname unavailable - failednick = e.msg[3] - nicks = list(e.network.nicks) - - if hasattr(e.network,'_nick_generator'): - if len(failednick) < len(e.network._next_nick): - e.network._nick_max_length = len(failednick) - e.network._next_nick = e.network._nick_generator.next() - e.network.raw('NICK %s' % e.network._next_nick) - e.network._nick_error |= (e.msg[1] == '432') - else: - e.network._nick_error = (e.msg[1] == '432') - if len(failednick) < len(e.network.nicks[0]): - e.network._nick_max_length = len(failednick) - else: - e.network._nick_max_length = 0 - e.network._nick_generator = _nick_generator(e.network) - e.network._next_nick = e.network._nick_generator.next() - e.network.raw('NICK %s' % e.network._next_nick) - - elif e.msg[1] == '431': #no nickname given--this shouldn't happen - pass - - elif e.msg[1] == '001': - e.network.got_nick = True - if e.network.me != e.msg[2]: - core.events.trigger( - 'Nick', network=e.network, window=e.window, - source=e.network.me, target=e.msg[2], address='', - text=e.msg[2] - ) - e.network.me = e.msg[2] - if hasattr(e.network,'_nick_generator'): - del e.network._nick_generator, e.network._nick_max_length, e.network._next_nick - - if e.msg[1] == "PING": - e.network.raw("PONG :%s" % e.msg[-1]) - e.done = True - - elif e.msg[1] == "JOIN": - e.channel = e.target - e.requested = e.network.norm_case(e.channel) in e.network.requested_joins - core.events.trigger("Join", e) - e.done = True - - elif e.msg[1] == "PART": - e.channel = e.target - e.requested = e.network.norm_case(e.channel) in e.network.requested_parts - e.text = ' '.join(e.msg[3:]) - core.events.trigger("Part", e) - e.done = True - - elif e.msg[1] in "MODE": - e.channel = e.target - e.text = ' '.join(e.msg[3:]) - core.events.trigger("Mode", e) - e.done = True - - elif e.msg[1] == "QUIT": - core.events.trigger('Quit', e) - e.done = True - - elif e.msg[1] == "KICK": - e.channel = e.msg[2] - e.target = e.msg[3] - core.events.trigger('Kick', e) - e.done = True - - elif e.msg[1] == "NICK": - core.events.trigger('Nick', e) - if e.network.me == e.source: - e.network.me = e.target - - e.done = True - - elif e.msg[1] == "PRIVMSG": - core.events.trigger('Text', e) - e.done = True - - elif e.msg[1] == "NOTICE": - core.events.trigger('Notice', e) - e.done = True - - elif e.msg[1] == "TOPIC": - core.events.trigger('Topic', e) - e.done = True - - elif e.msg[1] in ("376", "422"): #RPL_ENDOFMOTD - if e.network.status == irc.INITIALIZING: - e.network.status = irc.CONNECTED - core.events.trigger('Connect', e) - e.done = True - - elif e.msg[1] == "470": #forwarded from channel X to channel Y - if e.network.norm_case(e.msg[3]) in e.network.requested_joins: - e.network.requested_joins.discard(e.network.norm_case(e.msg[3])) - e.network.requested_joins.add(e.network.norm_case(e.msg[4])) - - elif e.msg[1] == "005": #RPL_ISUPPORT - for arg in e.msg[3:]: - if ' ' not in arg: #ignore "are supported by this server" - if '=' in arg: - name, value = arg.split('=', 1) - if value.isdigit(): - value = int(value) - else: - name, value = arg, '' - - #Workaround for broken servers (bahamut on EnterTheGame) - if name == 'PREFIX' and value[0] != '(': - continue - - #in theory, we're supposed to replace \xHH with the - # corresponding ascii character, but I don't think anyone - # really does this - e.network.isupport[name] = value - - if name == 'PREFIX': - new_prefixes = {} - modes, prefixes = value[1:].split(')') - for mode, prefix in zip(modes, prefixes): - new_prefixes[mode] = prefix - new_prefixes[prefix] = mode - e.network.prefixes = new_prefixes - -def setupSocketConnect(e): - e.network.got_nick = False - e.network.isupport = { - 'NETWORK': e.network.server, - 'PREFIX': '(ohv)@%+', - 'CHANMODES': 'b,k,l,imnpstr', - } - e.network.prefixes = {'o':'@', 'h':'%', 'v':'+', '@':'o', '%':'h', '+':'v'} - e.network.connect_timestamp = time.time() - e.network.requested_joins.clear() - e.network.requested_parts.clear() - e.network.on_channels.clear() - if hasattr(e.network,'_nick_generator'): - del e.network._nick_generator, e.network._nick_max_length, e.network._next_nick - if not e.done: - #this needs to be tested--anyone have a server that uses PASS? - if e.network.password: - e.network.raw("PASS :%s" % e.network.password) - e.network.raw("NICK %s" % e.network.nicks[0]) - e.network.raw("USER %s %s %s :%s" % - (e.network.username, "8", "*", e.network.fullname)) - #per rfc2812 these are username, user mode flags, unused, realname - - #e.network.me = None - e.done = True - -def onDisconnect(e): - if hasattr(e.network,'_reconnect_source'): - e.network._reconnect_source.unregister() - del e.network._reconnect_source - if hasattr(e.network,'connect_timestamp'): - if e.error and conf.get('autoreconnect',True): - delay = time.time() - e.network.connect_timestamp > 30 and 30 or 120 - def do_reconnect(): - if not e.network.status: - server(network=e.network) - def do_announce_reconnect(): - if not e.network.status: - windows.get_default(e.network).write("* Will reconnect in %s seconds.." % delay) - e.network._reconnect_source = ui.register_timer(delay*1000,do_reconnect) - e.network._reconnect_source = ui.register_idle(do_announce_reconnect) - -def onCloseNetwork(e): - e.network.quit() - if hasattr(e.network,'_reconnect_source'): - e.network._reconnect_source.unregister() - del e.network._reconnect_source - -def setdownDisconnect(e): - if hasattr(e.network,'connect_timestamp'): - del e.network.connect_timestamp - -def setupInput(e): - if not e.done: - if e.text.startswith(COMMAND_PREFIX) and not e.ctrl: - command = e.text[len(COMMAND_PREFIX):] - else: - command = 'say - %s' % e.text - - core.events.run(command, e.window, e.network) - - e.done = True - -def onCommandSay(e): - if isinstance(e.window, windows.ChannelWindow) or isinstance(e.window, windows.QueryWindow): - e.network.msg(e.window.id, ' '.join(e.args)) - else: - raise core.events.CommandError("There's no one here to speak to.") - -def onCommandMsg(e): - e.network.msg(e.args[0], ' '.join(e.args[1:])) - -def onCommandNotice(e): - e.network.notice(e.args[0], ' '.join(e.args[1:])) - -def onCommandQuery(e): - windows.new(windows.QueryWindow, e.network, e.args[0], core).activate() - if len(e.args) > 1: - message = ' '.join(e.args[1:]) - if message: #this is false if you do "/query nickname " - e.network.msg(e.args[0], ' '.join(e.args[1:])) - -def setupJoin(e): - if e.source == e.network.me: - chan = e.network.norm_case(e.channel) - e.network.on_channels.add(chan) - e.network.requested_joins.discard(chan) - -def setdownPart(e): - if e.source == e.network.me: - chan = e.network.norm_case(e.channel) - e.network.on_channels.discard(chan) - e.network.requested_parts.discard(chan) - -def setdownKick(e): - if e.target == e.network.me: - chan = e.network.norm_case(e.channel) - e.network.on_channels.discard(chan) - -def ischan(network, channel): - return network.norm_case(channel) in network.on_channels - -# make /nick work offline -def change_nick(network, nick): - if not network.status: - core.events.trigger( - 'Nick', - network=network, window=windows.get_default(network), - source=network.me, target=nick, address='', text=nick - ) - network.nicks[0] = nick - network.me = nick - else: - network.raw('NICK :%s' % nick) - -def onCommandNick(e): - default_nick = irc.default_nicks()[0] - if 't' not in e.switches and e.network.me == default_nick: - conf['nick'] = e.args[0] - import conf as _conf - _conf.save() - for network in set(w.network for w in core.manager): - if network.me == default_nick: - change_nick(network, e.args[0]) - else: - change_nick(e.network, e.args[0]) - -def setdownNick(e): - if e.source != e.network.me: - window = windows.get(windows.QueryWindow, e.network, e.source) - if window: - window.id = e.target - -# make /quit always disconnect us -def onCommandQuit(e): - if e.network.status: - e.network.quit(' '.join(e.args)) - else: - raise core.events.CommandError("We're not connected to a network.") - -def onCommandRaw(e): - if e.network.status >= irc.INITIALIZING: - e.network.raw(' '.join(e.args)) - else: - raise core.events.CommandError("We're not connected to a network.") - -onCommandQuote = onCommandRaw - -def onCommandJoin(e): - if e.args: - if e.network.status >= irc.INITIALIZING: - e.network.join(' '.join(e.args), requested = 'n' not in e.switches) - else: - raise core.events.CommandError("We're not connected.") - elif isinstance(e.window, windows.ChannelWindow): - e.window.network.join(e.window.id, requested = 'n' not in e.switches) - else: - raise core.events.CommandError("You must supply a channel.") - -def onCommandPart(e): - if e.args: - if e.network.status >= irc.INITIALIZING: - e.network.part(' '.join(e.args), requested = 'n' not in e.switches) - else: - raise core.events.CommandError("We're not connected.") - elif isinstance(e.window, windows.ChannelWindow): - e.window.network.part(e.window.id, requested = 'n' not in e.switches) - else: - raise core.events.CommandError("You must supply a channel.") - -def onCommandHop(e): - if e.args: - if e.network.status >= irc.INITIALIZING: - e.network.part(e.args[0], requested = False) - e.network.join(' '.join(e.args), requested = False) - else: - raise core.events.CommandError("We're not connected.") - elif isinstance(e.window, windows.ChannelWindow): - e.window.network.part(e.window.id, requested = False) - e.window.network.join(e.window.id, requested = False) - else: - raise core.events.CommandError("You must supply a channel.") - -#this should be used whereever a new irc.Network may need to be created -def server(server=None,port=6667,network=None,connect=True): - network_info = {} - - if server: - network_info["name"] = server - network_info["server"] = server - if port: - network_info["port"] = port - get_network_info(server, network_info) - - if not network: - network = irc.Network(**network_info) - windows.new(windows.StatusWindow, network, "status").activate() - else: - if "server" in network_info: - network.name = network_info['name'] - network.server = network_info['server'] - if not network.status: - #window = windows.get_default(network) - window = core.window - if window: - window.update() - if "port" in network_info: - network.port = network_info["port"] - - if network.status: - network.quit() - if connect: - network.connect() - core.window.write("* Connecting to %s on port %s" % (network.server, network.port)) - #windows.get_default(network).write( - # "* Connecting to %s on port %s" % (network.server, network.port) - # ) - - return network - -def onCommandServer(e): - host = port = None - - if e.args: - host = e.args[0] - - if ':' in host: - host, port = host.rsplit(':', 1) - port = int(port) - - elif len(e.args) > 1: - port = int(e.args[1]) - - else: - port = 6667 - - if 'm' in e.switches: - network = None - else: - network = e.network - - server(server=host, port=port, network=network, connect='o' not in e.switches) - -#see http://www.w3.org/Addressing/draft-mirashi-url-irc-01.txt -def onCommandIrcurl(e): - url = e.args[0] - - if url.startswith('irc://'): - url = url[6:] - - if not url.startswith('/'): - host, target = url.rsplit('/',1) - if ':' in host: - host, port = host.rsplit(':',1) - else: - port = 6667 - else: - host = None - port = 6667 - target = url - - if host: - if e.network and e.network.server == host: - network = e.network - else: - for w in list(windows.manager): - if w.network and w.network.server == host: - network = w.network - break - else: - for w in list(windows.manager): - if w.network and w.network.server == 'irc.default.org': - network = server(host,port,w.network) - break - else: - network = server(host,port) - - if ',' in target: - target, modifiers = target.split(',',1) - action = '' - else: - target = unquote(target) - if target[0] not in '#&+': - target = '#'+target - action = 'join %s' % target - - if network.status == irc.CONNECTED: - core.events.run(action, windows.get_default(network), network) - else: - if not hasattr(network,'temp_perform'): - network.temp_perform = [action] - else: - network.temp_perform.append(action) - -#commands that we need to add a : to but otherwise can send unchanged -#the dictionary contains the number of arguments we take without adding the : -trailing = { - 'away':0, - 'cnotice':2, - 'cprivmsg':2, - 'kick':2, - 'kill':1, - 'part':1, - 'squery':1, - 'squit':1, - 'topic':1, - 'wallops':0, - } - -needschan = { - 'topic':0, - 'invite':1, - 'kick':0, -# 'mode':0, #this is commonly used for channels, but can apply to users -# 'names':0, #with no parameters, this is supposed to give a list of all users; we may be able to safely ignore that. - } - -def setupCommand(e): - if not e.done: - if e.name in needschan and isinstance(e.window, windows.ChannelWindow): - valid_chan_prefixes = e.network.isupport.get('CHANTYPES', '#&+') - chan_pos = needschan[e.name] - - if len(e.args) > chan_pos: - if not e.args[chan_pos] or e.args[chan_pos][0] not in valid_chan_prefixes: - e.args.insert(chan_pos, e.window.id) - else: - e.args.append(e.window.id) - - if e.name in trailing: - trailing_pos = trailing[e.name] - - if len(e.args) > trailing_pos: - e.args[trailing_pos] = ':%s' % e.args[trailing_pos] - - e.text = '%s %s' % (e.name, ' '.join(e.args)) - -def setdownCommand(e): - if not e.done and e.network.status >= irc.INITIALIZING: - e.network.raw(e.text) - e.done = True - -def get_network_info(name, network_info): - conf_info = conf.get('networks', {}).get(name) - - if conf_info: - network_info['server'] = name - network_info.update(conf_info) - -def onStart(e): - for network in conf.get('start_networks', []): - server(server=network) - -def onConnect(e): - network_info = conf.get('networks', {}).get(e.network.name, {}) - - for command in network_info.get('perform', []): - while command.startswith(COMMAND_PREFIX): - command = command[len(COMMAND_PREFIX):] - core.events.run(command, e.window, e.network) - - tojoin = ','.join(network_info.get('join', [])) - if tojoin: - core.events.run('join -n %s' % tojoin, e.window, e.network) - - if hasattr(e.network,'temp_perform'): - for command in e.network.temp_perform: - core.events.run(command, e.window, e.network) - del e.network.temp_perform - -def isautojoin(network, channel): - try: - joinlist = conf['networks'][network.name]['join'] - except KeyError: - return False - normchannel = network.norm_case(channel) - for chan in joinlist: - if normchannel == network.norm_case(chan): - return True - return False - -def setautojoin(network, channel): - if 'networks' not in conf: - conf['networks'] = networks = {} - else: - networks = conf['networks'] - if network.name not in networks: - networks[network.name] = network_settings = {} - if 'start_networks' not in conf: - conf['start_networks'] = [] - conf['start_networks'].append(network.name) - else: - network_settings = networks[network.name] - - if 'join' not in network_settings: - network_settings['join'] = [channel] - else: - network_settings['join'].append(channel) - -def unsetautojoin(network, channel): - try: - joinlist = conf['networks'][network.name]['join'] - except KeyError: - return False - normchannel = network.norm_case(channel) - for i, chan in enumerate(joinlist[:]): - if normchannel == network.norm_case(chan): - joinlist.pop(i) - -def onChannelMenu(e): - def toggle_join(): - if isautojoin(e.network, e.channel): - unsetautojoin(e.network, e.channel) - else: - setautojoin(e.network, e.channel) - - e.menu.append(('Autojoin', isautojoin(e.network, e.channel), toggle_join)) diff --git a/services/console/lib/purk/scripts/keys.py b/services/console/lib/purk/scripts/keys.py deleted file mode 100644 index e26572cc..00000000 --- a/services/console/lib/purk/scripts/keys.py +++ /dev/null @@ -1,70 +0,0 @@ -import windows -import widgets -import irc - -shortcuts = { - '^b': '\x02', - '^u': '\x1F', - '^r': '\x16', - '^k': '\x03', - '^l': '\x04', - '^o': '\x0F', - } - -def onKeyPress(e): - if e.key in shortcuts: - e.window.input.insert(shortcuts[e.key]) - - elif e.key == '!c': - e.window.output.copy() - - elif e.key == 'Page_Up': - e.window.output.y = e.window.output.y - e.window.output.height / 2 - - elif e.key == 'Page_Down': - e.window.output.y = e.window.output.y + e.window.output.height / 2 - - elif e.key == '^Home': - e.window.output.y = 0 - - elif e.key == '^End': - e.window.output.y = e.window.output.ymax - - elif e.key in ('^Page_Up', '^Page_Down'): - winlist = list(windows.manager) - index = winlist.index(e.window) + ((e.key == '^Page_Down') and 1 or -1) - if 0 <= index < len(winlist): - winlist[index].activate() - - elif e.key == '!a': - winlist = list(windows.manager) - winlist = winlist[winlist.index(e.window):]+winlist - w = [w for w in winlist if widgets.HILIT in w.activity] - - if not w: - w = [w for w in winlist if widgets.TEXT in w.activity] - - if w: - windows.manager.set_active(w[0]) - - # tabbed browsing - elif e.key == '^t': - windows.new(windows.StatusWindow, irc.Network(), 'status').activate() - - elif e.key == '^w': - windows.manager.get_active().close() - - elif e.key == '^f': - window = windows.manager.get_active() - - find = widgets.FindBox(window) - - window.pack_start(find, expand=False) - - find.textbox.grab_focus() - - elif len(e.key) == 2 and e.key.startswith('!') and e.key[1].isdigit(): - n = int(e.key[1]) - if n and n <= len(core.manager): - list(core.manager)[n-1].activate() - #else e.key == "!0" diff --git a/services/console/lib/purk/scripts/theme.py b/services/console/lib/purk/scripts/theme.py deleted file mode 100644 index 7fda4d2d..00000000 --- a/services/console/lib/purk/scripts/theme.py +++ /dev/null @@ -1,366 +0,0 @@ -import time - -import windows -import widgets -import chaninfo - -from conf import conf - -textareas = {} -if 'font' in conf: - textareas['font'] = conf['font'] -if 'bg_color' in conf: - textareas['bg'] = conf['bg_color'] -if 'fg_color' in conf: - textareas['fg'] = conf['fg_color'] - -widgets.set_style("view", textareas) -widgets.set_style("nicklist", textareas) - -#copied pretty directly from something that was probably copied from wine sources -def RGBtoHSL(r, g, b): - maxval = max(r, g, b) - minval = min(r, g, b) - - luminosity = ((maxval + minval) * 240 + 255) // 510 - - if maxval == minval: - saturation = 0 - hue = 160 - else: - delta = maxval - minval - - if luminosity <= 120: - saturation = ((maxval+minval)//2 + delta*240) // (maxval + minval) - else: - saturation = ((150-maxval-minval)//2 + delta*240) // (150-maxval-minval) - - #sigh.. - rnorm = (delta//2 + maxval*40 - r*40)//delta - gnorm = (delta//2 + maxval*40 - g*40)//delta - bnorm = (delta//2 + maxval*40 - b*40)//delta - - if r == maxval: - hue = bnorm-gnorm - elif g == maxval: - hue = 80+rnorm-bnorm - else: - hue = 160+gnorm-rnorm - hue = hue % 240 - return hue, saturation, luminosity - -#copied from the same place -def huetoRGB(hue, mid1, mid2): - hue = hue % 240 - - if hue > 160: - return mid1 - elif hue > 120: - hue = 160 - hue - elif hue > 40: - return mid2 - return ((hue * (mid2 - mid1) + 20) // 40) + mid1 - -#this too -def HSLtoRGB(hue, saturation, luminosity): - if saturation != 0: - if luminosity > 120: - mid2 = saturation + luminosity - (saturation * luminosity + 120)//240 - else: - mid2 = ((saturation + 240) * luminosity + 120)//240 - - mid1 = luminosity * 2 - mid2 - - return tuple((huetoRGB(hue+x, mid1, mid2) * 255 + 120) // 240 for x in (80,0,-80)) - else: - value = luminosity * 255 // 240 - return value, value, value - -def gethashcolor(string): - h = hash(string) - rgb = HSLtoRGB(h%241, 100-h//241%61, 90) - return "%02x%02x%02x" % rgb - -#take an event e and trigger the highlight event if necessary -def hilight_text(e): - if not hasattr(e, 'Highlight'): - e.Highlight = [] - core.events.trigger('Highlight', e) - -#hilight own nick -def onHighlight(e): - lowertext = e.text.lower() - for word in conf.get('highlight_words', []) + [e.network.me] + e.network.nicks: - lowerword = word.lower() - pos = lowertext.find(lowerword, 0) - while pos != -1: - e.Highlight.append((pos, pos+len(word))) - pos = lowertext.find(lowerword, pos+1) - -def prefix(e): - return time.strftime(conf.get('timestamp', '')) - -def getsourcecolor(e): - address = getattr(e, "address", "") - if address: - if e.network.me == e.source: - e.network._my_address = address - elif e.network.me == e.source: - address = getattr(e.network, "_my_address", "") - if '@' in address: - address = address.split('@')[1] - if not address: - address = e.source - return "\x04%s" % gethashcolor(address) - -def format_source(e): - highlight = getattr(e, "Highlight", "") and '\x02' or '' - return "%s\x04%s%s" % (highlight, getsourcecolor(e), e.source) - -def format_info_source(e): - if e.source == e.network.me: - return "\x04%sYou" % (getsourcecolor(e)) - else: - return "\x04%s%s" % (getsourcecolor(e), e.source) - -def address(e): - #if e.source != e.network.me: - # return "%s " % info_in_brackets(e.address) - #else: - # return "" - return "" - -def text(e): - if e.text: - #return " %s" % info_in_brackets(e.text) - return ": \x0F%s" % e.text - else: - return "" - -def info_in_brackets(text): - return "(\x044881b6%s\x0F)" % text - -def pretty_time(secs): - times = ( - #("years", "year", 31556952), - ("weeks", "week", 604800), - ("days", "day", 86400), - ("hours", "hour", 3600), - ("minutes", "minute", 60), - ("seconds", "second", 1), - ) - if secs == 0: - return "0 seconds" - result = "" - for plural, singular, amount in times: - n, secs = divmod(secs, amount) - if n == 1: - result = result + " %s %s" % (n, singular) - elif n: - result = result + " %s %s" % (n, plural) - return result[1:] - -def onText(e): - hilight_text(e) - color = getsourcecolor(e) - to_write = prefix(e) - if e.network.me == e.target: # this is a pm - if e.window.id == e.network.norm_case(e.source): - to_write += "\x02<\x0F%s\x0F\x02>\x0F " % (format_source(e)) - else: - to_write += "\x02*\x0F%s\x0F\x02*\x0F " % (format_source(e)) - else: - if e.window.id == e.network.norm_case(e.target): - to_write += "\x02<\x0F%s\x0F\x02>\x0F " % (format_source(e)) - else: - to_write += "\x02<\x0F%s:%s\x0F\x02>\x0F " % (format_source(e), e.target) - to_write += e.text - - if e.Highlight: - e.window.write(to_write, widgets.HILIT) - else: - e.window.write(to_write, widgets.TEXT) - -def onOwnText(e): - color = getsourcecolor(e) - to_write = prefix(e) - if e.window.id == e.network.norm_case(e.target): - to_write += "\x02<\x0F%s\x0F\x02>\x0F %s" % (format_source(e), e.text) - else: - to_write += "%s->\x0F \x02*\x0F%s\x0F\x02*\x0F %s" % (color, e.target, e.text) - - e.window.write(to_write) - -def onAction(e): - hilight_text(e) - color = color = getsourcecolor(e) - to_write = "%s\x02*\x0F %s\x0F %s" % (prefix(e), format_source(e), e.text) - - if e.Highlight: - e.window.write(to_write, widgets.HILIT) - else: - e.window.write(to_write, widgets.TEXT) - -def onOwnAction(e): - color = getsourcecolor(e) - to_write = "%s\x02*\x0F %s\x0F %s" % (prefix(e), format_source(e), e.text) - - e.window.write(to_write) - -def onNotice(e): - hilight_text(e) - color = getsourcecolor(e) - to_write = prefix(e) - if e.network.me == e.target: # this is a pm - to_write += "\x02-\x0F%s\x0F\x02-\x0F " % (format_source(e)) - else: - to_write += "\x02-\x0F%s:%s\x0F\x02-\x0F " % (format_source(e), e.target) - to_write += e.text - - e.window.write(to_write, (e.Highlight and widgets.HILIT) or widgets.TEXT) - -def onOwnNotice(e): - color = getsourcecolor(e) - to_write = "%s-> \x02-\x02%s\x0F\x02-\x0F %s" % (prefix(e), e.target, e.text) - - e.window.write(to_write) - -def onCtcp(e): - color = getsourcecolor(e) - to_write = "%s\x02[\x02%s\x0F\x02]\x0F %s" % (prefix(e), format_source(e), e.text) - - if not e.quiet: - e.window.write(to_write) - -def onCtcpReply(e): - color = getsourcecolor(e) - to_write = "%s%s--- %s reply from %s:\x0F %s" % (prefix(e), color, e.name.capitalize(), format_source(e), ' '.join(e.args)) - - window = windows.manager.get_active() - if window.network != e.network: - window = windows.get_default(e.network) - window.write(to_write, widgets.TEXT) - -def onJoin(e): - if e.source == e.network.me: - to_write = "%s%s %sjoin %s" % (prefix(e), format_info_source(e), address(e), e.target) - else: - to_write = "%s%s %sjoins %s" % (prefix(e), format_info_source(e), address(e), e.target) - - e.window.write(to_write) - -def onPart(e): - if e.source == e.network.me: - to_write = "%s%s leave %s%s" % (prefix(e), format_info_source(e), e.target, text(e)) - else: - to_write = "%s%s leaves %s%s" % (prefix(e), format_info_source(e), e.target, text(e)) - - e.window.write(to_write) - -def onKick(e): - if e.source == e.network.me: - to_write = "%s%s kick %s%s" % (prefix(e), format_info_source(e), e.target, text(e)) - else: - to_write = "%s%s kicks %s%s" % (prefix(e), format_info_source(e), e.target, text(e)) - - e.window.write(to_write, (e.target == e.network.me and widgets.HILIT) or widgets.EVENT) - -def onMode(e): - if e.source == e.network.me: - to_write = "%s%s set mode:\x0F %s" % (prefix(e), format_info_source(e), e.text) - else: - to_write = "%s%s sets mode:\x0F %s" % (prefix(e), format_info_source(e), e.text) - - e.window.write(to_write) - -def onQuit(e): - to_write = "%s%s leaves%s" % (prefix(e), format_info_source(e), text(e)) - - for channame in chaninfo.channels(e.network): - if chaninfo.ison(e.network, channame, e.source): - window = windows.get(windows.ChannelWindow, e.network, channame, core) - if window: - window.write(to_write) - -def onNick(e): - color = getsourcecolor(e) - if e.source == e.network.me: - to_write = "%s%sYou are now known as %s" % (prefix(e), color, e.target) - else: - to_write = "%s%s%s is now known as %s" % (prefix(e), color, e.source, e.target) - - if e.source == e.network.me: - for window in windows.get_with(core.manager, network=e.network): - window.write(to_write) - else: - for channame in chaninfo.channels(e.network): - if chaninfo.ison(e.network,channame,e.source): - window = windows.get(windows.ChannelWindow, e.network, channame) - if window: - window.write(to_write) - -def onTopic(e): - if e.source == e.network.me: - to_write = "%s%s set topic:\x0F %s" % (prefix(e), format_info_source(e), e.text) - else: - to_write = "%s%s sets topic:\x0F %s" % (prefix(e), format_info_source(e), e.text) - - e.window.write(to_write) - -def onRaw(e): - if not e.quiet: - if e.msg[1].isdigit(): - if e.msg[1] == '332': - window = windows.get(windows.ChannelWindow, e.network, e.msg[3], core) or e.window - window.write( - "%sTopic on %s is: %s" % - (prefix(e), e.msg[3], e.text) - ) - - elif e.msg[1] == '333': - window = windows.get(windows.ChannelWindow, e.network, e.msg[3], core) or e.window - window.write( - "%sTopic on %s set by %s at time %s" % - (prefix(e), e.msg[3], e.msg[4], time.ctime(int(e.msg[5]))) - ) - - elif e.msg[1] == '329': #RPL_CREATIONTIME - pass - - elif e.msg[1] == '311': #RPL_WHOISUSER - e.window.write("* %s is %s@%s * %s" % (e.msg[3], e.msg[4], e.msg[5], e.msg[7])) - - elif e.msg[1] == '312': #RPL_WHOISSERVER - e.window.write("* %s on %s (%s)" % (e.msg[3], e.msg[4], e.msg[5])) - - elif e.msg[1] == '317': #RPL_WHOISIDLE - e.window.write("* %s has been idle for %s" % (e.msg[3], pretty_time(int(e.msg[4])))) - if e.msg[5].isdigit(): - e.window.write("* %s signed on %s" % (e.msg[3], time.ctime(int(e.msg[5])))) - - elif e.msg[1] == '319': #RPL_WHOISCHANNELS - e.window.write("* %s on channels: %s" % (e.msg[3], e.msg[4])) - - elif e.msg[1] == '330': #RPL_WHOISACCOUNT - #this appears to conflict with another raw, so if there's anything weird about it, - # we fall back on the default - if len(e.msg) == 6 and not e.msg[4].isdigit() and not e.msg[5].isdigit(): - e.window.write("* %s %s %s" % (e.msg[3], e.msg[5], e.msg[4])) - else: - e.window.write("* %s" % ' '.join(e.msg[3:])) - - else: - e.window.write("* %s" % ' '.join(e.msg[3:])) - elif e.msg[1] == 'ERROR': - e.window.write("Error: %s" % e.text) - -def onDisconnect(e): - to_write = '%s* Disconnected' % prefix(e) - if e.error: - to_write += ' (%s)' % e.error - - for window in windows.get_with(network=e.network): - if isinstance(window, windows.StatusWindow): - window.write(to_write, widgets.TEXT) - else: - window.write(to_write, widgets.EVENT) diff --git a/services/console/lib/purk/scripts/timeout.py b/services/console/lib/purk/scripts/timeout.py deleted file mode 100755 index 2f0f5852..00000000 --- a/services/console/lib/purk/scripts/timeout.py +++ /dev/null @@ -1,45 +0,0 @@ -import time - -import ui -from conf import conf - -def setupRaw(e): - e.network._message_timeout = False - -def onSocketConnect(e): - timeout = conf.get("server_traffic_timeout", 120)*1000 - e.network._message_timeout = False - if timeout: - e.network._message_timeout_source = ui.register_timer(timeout, check_timeout, e.network) - else: - e.network._message_timeout_source = None - -def check_timeout(network): - if network._message_timeout: - network.raw("PING %s" % network.me) - timeout = conf.get("server_death_timeout", 240)*1000 - network._message_timeout_source = ui.register_timer(timeout, check_death_timeout, network) - return False - else: - network._message_timeout = True - return True # call this function again - -def check_death_timeout(network): - if network._message_timeout: - network.raw("QUIT :Server missing, presumed dead") - network.disconnect(error="The server seems to have stopped talking to us") - else: - network._message_timeout = False - timeout = conf.get("server_traffic_timeout", 120)*1000 - if timeout: - network._message_timeout_source = ui.register_timer(timeout, check_timeout, network) - else: - network._message_timeout_source = None - -def onDisconnect(e): - try: - if e.network._message_timeout_source: - e.network._message_timeout_source.unregister() - e.network._message_timeout_source = None - except AttributeError: - pass diff --git a/services/console/lib/purk/scripts/ui_script.py b/services/console/lib/purk/scripts/ui_script.py deleted file mode 100644 index 459de96a..00000000 --- a/services/console/lib/purk/scripts/ui_script.py +++ /dev/null @@ -1,132 +0,0 @@ -import irc -import ui -import windows -import irc_script -from conf import conf - -# FIXME: meh still might want rid of these, I'm not sure yet - -def onActive(e): - e.window.activity = None - - ui.register_idle(windows.manager.set_title) - -def setupNick(e): - if e.source == e.network.me: - for w in windows.get_with(core.manager, network=e.network): - try: - w.nick_label.update(e.target) - except AttributeError: - pass - -def onExit(e): - for n in set(w.network for w in windows.manager): - if n: - n.quit() - -def setupJoin(e): - if e.source == e.network.me: - window = windows.get(windows.StatusWindow, e.network, 'status', core) - - if window and not conf.get('status'): - window.mutate(windows.ChannelWindow, e.network, e.target) - else: - window = windows.new(windows.ChannelWindow, e.network, e.target, core) - - if e.requested: - window.activate() - - e.window = windows.get(windows.ChannelWindow, e.network, e.target, core) or e.window - -def setupText(e): - if e.target == e.network.me: - e.window = windows.new(windows.QueryWindow, e.network, e.source, core) - else: - e.window = \ - windows.get(windows.ChannelWindow, e.network, e.target, core) or \ - windows.get(windows.QueryWindow, e.network, e.source, core) or \ - e.window - -setupAction = setupText - -def setupNotice(e): - if e.target != e.network.me: - e.window = \ - windows.get(windows.ChannelWindow, e.network, e.target, core) or e.window - -def setupOwnText(e): - e.window = \ - windows.get(windows.ChannelWindow, e.network, e.target, core) or \ - windows.get(windows.QueryWindow, e.network, e.target, core) or \ - e.window - -setupOwnAction = setupOwnText - -def setdownPart(e): - if e.source == e.network.me: - window = windows.get(windows.ChannelWindow, e.network, e.target, core) - - if window: - cwindows = list(windows.get_with( - network=window.network, - wclass=windows.ChannelWindow - )) - - if len(cwindows) == 1 and not list(windows.get_with(network=window.network, wclass=windows.StatusWindow)): - window.mutate(windows.StatusWindow, e.network, 'status') - if e.requested: - window.activate() - elif e.requested: - window.close() - -def onClose(e): - nwindows = list(windows.get_with(core.manager, network=e.window.network)) - - if isinstance(e.window, windows.ChannelWindow): - cwindows = list(windows.get_with(core.manager, - network=e.window.network, - wclass=windows.ChannelWindow - )) - - #if we only have one window for the network, don't bother to part as - # we'll soon be quitting anyway - if len(nwindows) != 1 and irc_script.ischan(e.window.network, e.window.id): - e.window.network.part(e.window.id) - - if len(nwindows) == 1: - core.events.trigger("CloseNetwork", window=e.window, network=e.window.network) - - elif isinstance(e.window, windows.StatusWindow) and conf.get('status'): - core.events.trigger("CloseNetwork", window=e.window, network=e.window.network) - for window in nwindows: - if window != e.window: - window.close() - - if len(core.manager) == 1: - windows.new(windows.StatusWindow, irc.Network(), "status", core) - -def onConnecting(e): - return - window = windows.get_default(e.network) - if window: - window.update() - -onDisconnect = onConnecting - -def setupPart(e): - e.window = windows.get(windows.ChannelWindow, e.network, e.target, core) or e.window - -setupTopic = setupPart - -def setupKick(e): - e.window = windows.get(windows.ChannelWindow, e.network, e.channel, core) or e.window - -def setupMode(e): - if e.target != e.network.me: - e.window = windows.get(windows.ChannelWindow, e.network, e.target, core) or e.window - -def onWindowMenu(e): - if isinstance(e.window, windows.ChannelWindow): - e.channel = e.window.id - e.network = e.window.network - core.events.trigger('ChannelMenu', e) diff --git a/services/console/lib/purk/servers.py b/services/console/lib/purk/servers.py deleted file mode 100644 index 19ce23c1..00000000 --- a/services/console/lib/purk/servers.py +++ /dev/null @@ -1,51 +0,0 @@ -import gtk - -import windows -from conf import conf - -if 'networks' not in conf: - conf['networks'] = {} - -def server_get_data(network_info): - if 'port' in network_info: - return "%s:%s" % ( - network_info.get('server', '') , network_info.get('port') - ) - else: - return network_info.get('server', '') - -def server_set_data(text, network_info): - if ':' in text: - network_info['server'], port = text.rsplit(':',1) - network_info['port'] = int(port) - else: - network_info['server'] = text - network_info.pop('port', None) - -def channels_get_data(network_info): - return '\n'.join(network_info.get('join', ())) - -def channels_set_data(text, network_info): - network_info['join'] = [] - - for line in text.split('\n'): - for chan in line.split(','): - if chan: - network_info['join'].append(chan.strip()) - -def perform_get_data(network_info): - return '\n'.join(network_info.get('perform', ())) - -def perform_set_data(text, network_info): - network_info['perform'] = [line for line in text.split('\n') if line] - -def autoconnect_set_data(do_autoconnect, network): - if 'start_networks' not in conf: - conf['start_networks'] = [] - - # note (n in C) != w - if (network in conf.get('start_networks')) != do_autoconnect: - if do_autoconnect: - conf.get('start_networks').append(network) - else: - conf.get('start_networks').remove(network) diff --git a/services/console/lib/purk/ui.py b/services/console/lib/purk/ui.py deleted file mode 100644 index 6e1e28f1..00000000 --- a/services/console/lib/purk/ui.py +++ /dev/null @@ -1,105 +0,0 @@ -import sys -import os -import thread -import socket -import signal -import traceback - -import commands - -import gobject - -__sys_path = list(sys.path) -import gtk -sys.path = __sys_path - -import irc -from conf import conf - -import widgets -import windows - -# Running from same package dir -urkpath = os.path.dirname(__file__) - -def path(filename=""): - if filename: - return os.path.join(urkpath, filename) - else: - return urkpath - -# Priority Constants -PRIORITY_HIGH = gobject.PRIORITY_HIGH -PRIORITY_DEFAULT = gobject.PRIORITY_DEFAULT -PRIORITY_HIGH_IDLE = gobject.PRIORITY_HIGH_IDLE -PRIORITY_DEFAULT_IDLE = gobject.PRIORITY_DEFAULT_IDLE -PRIORITY_LOW = gobject.PRIORITY_LOW - - -if os.access(path('profile'),os.F_OK) or os.path.expanduser("~") == "~": - userpath = path('profile') - if not os.access(userpath,os.F_OK): - os.mkdir(userpath) - if not os.access(os.path.join(userpath,'scripts'),os.F_OK): - os.mkdir(os.path.join(userpath,'scripts')) -else: - userpath = os.path.join(os.path.expanduser("~"), ".urk") - if not os.access(userpath,os.F_OK): - os.mkdir(userpath, 0700) - if not os.access(os.path.join(userpath,'scripts'),os.F_OK): - os.mkdir(os.path.join(userpath,'scripts'), 0700) - - -def set_clipboard(text): - gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD).set_text(text) - gtk.clipboard_get(gtk.gdk.SELECTION_PRIMARY).set_text(text) - -class Source(object): - __slots__ = ['enabled'] - def __init__(self): - self.enabled = True - def unregister(self): - self.enabled = False - -class GtkSource(object): - __slots__ = ['tag'] - def __init__(self, tag): - self.tag = tag - def unregister(self): - gobject.source_remove(self.tag) - -def register_idle(f, *args, **kwargs): - priority = kwargs.pop("priority",PRIORITY_DEFAULT_IDLE) - def callback(): - return f(*args, **kwargs) - return GtkSource(gobject.idle_add(callback, priority=priority)) - -def register_timer(time, f, *args, **kwargs): - priority = kwargs.pop("priority",PRIORITY_DEFAULT_IDLE) - def callback(): - return f(*args, **kwargs) - return GtkSource(gobject.timeout_add(time, callback, priority=priority)) - -def fork(cb, f, *args, **kwargs): - is_stopped = Source() - def thread_func(): - try: - result, error = f(*args, **kwargs), None - except Exception, e: - result, error = None, e - - if is_stopped.enabled: - def callback(): - if is_stopped.enabled: - cb(result, error) - - gobject.idle_add(callback) - - thread.start_new_thread(thread_func, ()) - return is_stopped - -set_style = widgets.set_style - -def we_get_signal(*what): - gobject.idle_add(windows.manager.exit) - diff --git a/services/console/lib/purk/urk_trace.py b/services/console/lib/purk/urk_trace.py deleted file mode 100644 index 4b55b46d..00000000 --- a/services/console/lib/purk/urk_trace.py +++ /dev/null @@ -1,70 +0,0 @@ -import sys -import commands -import linecache - -import time - -last_mem = [0] - -def traceit_memory(frame, event, arg): - if event == "line": - mem = int(" " + commands.getoutput( - "ps -eo cmd,rss | grep urk_trace.py | grep -v grep" - ).split(" ")[-1]) - - if mem > last_mem[0]: - last_mem[0] = mem - - mem = str(mem) - - filename = frame.f_globals["__file__"] - - if filename.endswith(".pyc") or filename.endswith(".pyo"): - filename = filename[:-1] - - name = frame.f_globals["__name__"] - - lineno = frame.f_lineno - line = linecache.getline(filename,lineno).rstrip() - - data = "%s:%i: %s" % (name, lineno, line) - - print "%s%s" % (data, mem.rjust(80 - len(data))) - - return traceit_memory - -lines = {} - -def traceit(frame, event, arg): - if event == "line": - try: - filename = frame.f_globals["__file__"] - - if filename.endswith(".pyc") or filename.endswith(".pyo"): - filename = filename[:-1] - - name = frame.f_globals["__name__"] - - lineno = frame.f_lineno - line = linecache.getline(filename,lineno).rstrip() - - data = "%s:%i: %s" % (name, lineno, line) - - print time.time(), data - - #if data in lines: - # lines[data] += 1 - #else: - # lines[data] = 1 - - except Exception, e: - print e - - return traceit - -def main(): - import urk - urk.main() - -sys.settrace(traceit) -main() diff --git a/services/console/lib/purk/widgets.py b/services/console/lib/purk/widgets.py deleted file mode 100644 index 1ad3cb81..00000000 --- a/services/console/lib/purk/widgets.py +++ /dev/null @@ -1,811 +0,0 @@ -import codecs - -import gobject -import gtk -import gtk.gdk -import pango - -from conf import conf -import parse_mirc -import windows - -import servers - -# Window activity Constants -HILIT = 'h' -TEXT ='t' -EVENT = 'e' - -ACTIVITY_MARKUP = { - HILIT: "%s", - TEXT: "%s", - EVENT: "%s", - } - -# This holds all tags for all windows ever -tag_table = gtk.TextTagTable() - -link_tag = gtk.TextTag('link') -link_tag.set_property('underline', pango.UNDERLINE_SINGLE) - -indent_tag = gtk.TextTag('indent') -indent_tag.set_property('indent', -20) - -tag_table.add(link_tag) -tag_table.add(indent_tag) - -#FIXME: MEH hates dictionaries, they remind him of the bad words -styles = {} - -def style_me(widget, style): - widget.set_style(styles.get(style)) - -def set_style(widget_name, style): - if style: - # FIXME: find a better way... - dummy = gtk.Label() - dummy.set_style(None) - - def apply_style_fg(value): - dummy.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse(value)) - - def apply_style_bg(value): - dummy.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(value)) - - def apply_style_font(value): - dummy.modify_font(pango.FontDescription(value)) - - style_functions = ( - ('fg', apply_style_fg), - ('bg', apply_style_bg), - ('font', apply_style_font), - ) - - for name, f in style_functions: - if name in style: - f(style[name]) - - style = dummy.rc_get_style() - else: - style = None - - styles[widget_name] = style - -def menu_from_list(alist): - while alist and not alist[-1]: - alist.pop(-1) - - last = None - for item in alist: - if item != last: - if item: - if len(item) == 2: - name, function = item - - menuitem = gtk.ImageMenuItem(name) - - elif len(item) == 3: - name, stock_id, function = item - - if isinstance(stock_id, bool): - menuitem = gtk.CheckMenuItem(name) - menuitem.set_active(stock_id) - else: - menuitem = gtk.ImageMenuItem(stock_id) - - if isinstance(function, list): - submenu = gtk.Menu() - for subitem in menu_from_list(function): - submenu.append(subitem) - menuitem.set_submenu(submenu) - - else: - menuitem.connect("activate", lambda a, f: f(), function) - - yield menuitem - - else: - yield gtk.SeparatorMenuItem() - - last = item - -class Nicklist(gtk.TreeView): - def click(self, event): - if event.button == 3: - x, y = event.get_coords() - - (data,), path, x, y = self.get_path_at_pos(int(x), int(y)) - - c_data = self.events.data(window=self.win, data=self[data], menu=[]) - - self.events.trigger("ListRightClick", c_data) - - if c_data.menu: - menu = gtk.Menu() - for item in menu_from_list(c_data.menu): - menu.append(item) - menu.show_all() - menu.popup(None, None, None, event.button, event.time) - - elif event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: - x, y = event.get_coords() - - (data,), path, x, y = self.get_path_at_pos(int(x), int(y)) - - self.events.trigger("ListDoubleClick", window=self.win, target=self[data]) - - def __getitem__(self, pos): - return self.get_model()[pos][0] - - def __setitem__(self, pos, name_markup): - realname, markedupname, sortkey = name_markup - - self.get_model()[pos] = realname, markedupname, sortkey - - def __len__(self): - return len(self.get_model()) - - def index(self, item): - for i, x in enumerate(self): - if x == item: - return i - - return -1 - - def append(self, realname, markedupname, sortkey): - self.get_model().append((realname, markedupname, sortkey)) - - def insert(self, pos, realname, markedupname, sortkey): - self.get_model().insert(pos, (realname, markedupname, sortkey)) - - def replace(self, names): - self.set_model(gtk.ListStore(str, str, str)) - - self.insert_column_with_attributes( - 0, '', gtk.CellRendererText(), markup=1 - ).set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - - for name in names: - self.append(*name) - - self.get_model().set_sort_column_id(2, gtk.SORT_ASCENDING) - - def remove(self, realname): - index = self.index(realname) - - if index == -1: - raise ValueError - - self.get_model().remove(self.get_model().iter_nth_child(None, index)) - - def clear(self): - self.get_model().clear() - - def __iter__(self): - return (r[0] for r in self.get_model()) - - def __init__(self, window, core): - self.win = window - self.core = core - self.events = core.events - - gtk.TreeView.__init__(self) - - self.replace(()) - - self.set_headers_visible(False) - self.set_property("fixed-height-mode", True) - self.connect("button-press-event", Nicklist.click) - self.connect_after("button-release-event", lambda *a: True) - - style_me(self, "nicklist") - -# Label used to display/edit your current nick on a network -class NickEditor(gtk.EventBox): - def nick_change(self, entry): - oldnick, newnick = self.label.get_text(), entry.get_text() - - if newnick and newnick != oldnick: - self.events.run('nick %s' % newnick, self.win, self.win.network) - - self.win.input.grab_focus() - - def update(self, nick=None): - self.label.set_text(nick or self.win.network.me) - - def to_edit_mode(self, widget, event): - if self.label not in self.get_children(): - return - - if getattr(event, 'button', None) == 3: - c_data = self.events.data(window=self.win, menu=[]) - self.events.trigger("NickEditMenu", c_data) - - if c_data.menu: - menu = gtk.Menu() - for item in menu_from_list(c_data.menu): - menu.append(item) - menu.show_all() - menu.popup(None, None, None, event.button, event.time) - - else: - entry = gtk.Entry() - entry.set_text(self.label.get_text()) - entry.connect('activate', self.nick_change) - entry.connect('focus-out-event', self.to_show_mode) - - self.remove(self.label) - self.add(entry) - self.window.set_cursor(None) - - entry.show() - entry.grab_focus() - - def to_show_mode(self, widget, event): - self.remove(widget) - self.add(self.label) - self.win.input.grab_focus() - self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.XTERM)) - - def __init__(self, window, core): - gtk.EventBox.__init__(self) - self.events = core.events - self.win = window - - self.label = gtk.Label() - self.label.set_padding(5, 0) - self.add(self.label) - - self.connect("button-press-event", self.to_edit_mode) - - self.update() - - self.connect( - "realize", - lambda *a: self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.XTERM)) - ) - -# The entry which you type in to send messages -class TextInput(gtk.Entry): - # Generates an input event - def entered_text(self, ctrl): - #for a in globals(): - # print a - #print events.__file__ - #self.core.run_command(self.text) - for line in self.text.splitlines(): - if line: - e_data = self.events.data( - window=self.win, network=self.win.network, - text=line, ctrl=ctrl - ) - self.events.trigger('Input', e_data) - if not e_data.done: - self.events.run(line, self.win, self.win.network) - - self.text = '' - - def _set_selection(self, s): - if s: - self.select_region(*s) - else: - self.select_region(self.cursor, self.cursor) - - #some nice toys for the scriptors - text = property(gtk.Entry.get_text, gtk.Entry.set_text) - cursor = property(gtk.Entry.get_position, gtk.Entry.set_position) - selection = property(gtk.Entry.get_selection_bounds, _set_selection) - - def insert(self, text): - self.do_insert_at_cursor(self, text) - - #hack to stop it selecting the text when we focus - def do_grab_focus(self): - temp = self.text, (self.selection or (self.cursor,)*2) - self.text = '' - gtk.Entry.do_grab_focus(self) - self.text, self.selection = temp - - def keypress(self, event): - keychar = ( - (gtk.gdk.CONTROL_MASK, '^'), - (gtk.gdk.SHIFT_MASK, '+'), - (gtk.gdk.MOD1_MASK, '!') - ) - - key = '' - for keymod, char in keychar: - # we make this an int, because otherwise it leaks - if int(event.state) & keymod: - key += char - key += gtk.gdk.keyval_name(event.keyval) - - self.events.trigger('KeyPress', key=key, string=event.string, window=self.win) - - if key == "^Return": - self.entered_text(True) - - up = gtk.gdk.keyval_from_name("Up") - down = gtk.gdk.keyval_from_name("Down") - tab = gtk.gdk.keyval_from_name("Tab") - - return event.keyval in (up, down, tab) - - def __init__(self, window, core): - gtk.Entry.__init__(self) - self.events = core.events - self.core = core - self.win = window - - # we don't want key events to propogate so we stop them in connect_after - self.connect('key-press-event', TextInput.keypress) - self.connect_after('key-press-event', lambda *a: True) - - self.connect('activate', TextInput.entered_text, False) - -gobject.type_register(TextInput) - -def prop_to_gtk(textview, (prop, val)): - if val == parse_mirc.BOLD: - val = pango.WEIGHT_BOLD - - elif val == parse_mirc.UNDERLINE: - val = pango.UNDERLINE_SINGLE - - return {prop: val} - -def word_from_pos(text, pos): - if text[pos] == ' ': - return ' ', pos, pos+1 - - else: - fr = text[:pos].split(" ")[-1] - to = text[pos:].split(" ")[0] - - return fr + to, pos - len(fr), pos + len(to) - -def get_iter_at_coords(view, x, y): - return view.get_iter_at_location( - *view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, int(x), int(y)) - ) - -def get_event_at_iter(view, iter, core): - buffer = view.get_buffer() - - line_strt = buffer.get_iter_at_line(iter.get_line()) - line_end = line_strt.copy() - line_end.forward_lines(1) - - pos = iter.get_line_offset() - - #Caveat: text must be a unicode string, not utf-8 encoded; otherwise our - # offsets will be off when we use anything outside 7-bit ascii - #gtk.TextIter.get_text returns unicode but gtk.TextBuffer.get_text does not - text = line_strt.get_text(line_end).rstrip("\n") - - word, fr, to = word_from_pos(text, pos) - - return core.events.data( - window=view.win, pos=pos, text=text, - target=word, target_fr=fr, target_to=to, - ) - -class TextOutput(gtk.TextView): - def copy(self): - startend = self.get_buffer().get_selection_bounds() - - tagsandtext = [] - if startend: - start, end = startend - - while not start.equal(end): - tags_at_iter = {} - for tag in start.get_tags(): - try: - tagname, tagval = eval(tag.get_property('name')) - tags_at_iter[tagname] = tagval - except NameError: - continue - - tagsandtext.append((dict(tags_at_iter), start.get_char())) - start.forward_char() - - text = parse_mirc.unparse_mirc(tagsandtext) - - gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD).set_text(text) - gtk.clipboard_get(gtk.gdk.SELECTION_PRIMARY).set_text(text) - - return text - - def clear(self): - self.get_buffer().set_text('') - - def get_y(self): - rect = self.get_visible_rect() - return rect.y - - def set_y(self,y): - iter = self.get_iter_at_location(0, y) - if self.get_iter_location(iter).y < y: - self.forward_display_line(iter) - yalign = float(self.get_iter_location(iter).y-y)/self.height - self.scroll_to_iter(iter, 0, True, 0, yalign) - - self.check_autoscroll() - - def get_ymax(self): - buffer = self.get_buffer() - return sum(self.get_line_yrange(buffer.get_end_iter())) - self.height - - def get_height(self): - return self.get_visible_rect().height - - y = property(get_y, set_y) - ymax = property(get_ymax) - height = property(get_height) - - # the unknowing print weird things to our text widget function - def write(self, text, line_ending='\n', fg=None): - if not isinstance(text, unicode): - try: - text = codecs.utf_8_decode(text)[0] - except: - text = codecs.latin_1_decode(text)[0] - tags, text = parse_mirc.parse_mirc(text) - - if fg: - tags.append({'data': ("foreground", isinstance(fg, basestring) and ('#%s'%fg) or parse_mirc.get_mirc_color(fg)), 'from': 0, 'to': len(text)}) - - buffer = self.get_buffer() - - cc = buffer.get_char_count() - - buffer.insert_with_tags_by_name( - buffer.get_end_iter(), - text + line_ending, - 'indent' - ) - - for tag in tags: - tag_name = str(tag['data']) - - if not tag_table.lookup(tag_name): - buffer.create_tag(tag_name, **prop_to_gtk(self, tag['data'])) - - buffer.apply_tag_by_name( - tag_name, - buffer.get_iter_at_offset(tag['from'] + cc), - buffer.get_iter_at_offset(tag['to'] + cc) - ) - - def popup(self, menu): - hover_iter = get_iter_at_coords(self, *self.hover_coords) - - menuitems = [] - if not hover_iter.ends_line(): - c_data = get_event_at_iter(self, hover_iter) - c_data.menu = [] - - self.events.trigger("RightClick", c_data) - - menuitems = c_data.menu - - if not menuitems: - c_data = self.events.data(menu=[]) - self.events.trigger("MainMenu", c_data) - - menuitems = c_data.menu - - for child in menu.get_children(): - menu.remove(child) - - for item in menu_from_list(menuitems): - menu.append(item) - - menu.show_all() - - def mousedown(self, event): - if event.button == 3: - self.hover_coords = event.get_coords() - - def mouseup(self, event): - if not self.get_buffer().get_selection_bounds(): - if event.button == 1: - hover_iter = get_iter_at_coords(self, event.x, event.y) - - if not hover_iter.ends_line(): - c_data = get_event_at_iter(self, hover_iter, self.core) - - self.events.trigger("Click", c_data) - - if self.is_focus(): - self.win.focus() - - def clear_hover(self, _event=None): - buffer = self.get_buffer() - - for fr, to in self.linking: - buffer.remove_tag_by_name( - "link", - buffer.get_iter_at_mark(fr), - buffer.get_iter_at_mark(to) - ) - - self.linking = set() - self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(None) - - def hover(self, event): - if self.linking: - self.clear_hover() - - hover_iter = get_iter_at_coords(self, event.x, event.y) - - if not hover_iter.ends_line(): - h_data = get_event_at_iter(self, hover_iter, self.core) - h_data.tolink = set() - - self.events.trigger("Hover", h_data) - - if h_data.tolink: - buffer = self.get_buffer() - - offset = buffer.get_iter_at_line( - hover_iter.get_line() - ).get_offset() - - for fr, to in h_data.tolink: - fr = buffer.get_iter_at_offset(offset + fr) - to = buffer.get_iter_at_offset(offset + to) - - buffer.apply_tag_by_name("link", fr, to) - - self.linking.add( - (buffer.create_mark(None, fr), - buffer.create_mark(None, to)) - ) - - self.get_window( - gtk.TEXT_WINDOW_TEXT - ).set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2)) - - self.get_pointer() - - def scroll(self, _allocation=None): - if self.autoscroll: - def do_scroll(): - self.scroller.value = self.scroller.upper - self.scroller.page_size - self._scrolling = False - - if not self._scrolling: - self._scrolling = gobject.idle_add(do_scroll) - - def check_autoscroll(self, *args): - def set_to_scroll(): - self.autoscroll = self.scroller.value + self.scroller.page_size >= self.scroller.upper - - gobject.idle_add(set_to_scroll) - - def __init__(self, core, window, buffer=None): - if not buffer: - buffer = gtk.TextBuffer(tag_table) - - gtk.TextView.__init__(self, buffer) - self.core = core - self.events = core.events - self.win = window - - self.set_size_request(0, -1) - - self.set_wrap_mode(gtk.WRAP_WORD_CHAR) - self.set_editable(False) - self.set_cursor_visible(False) - - self.set_property("left-margin", 3) - self.set_property("right-margin", 3) - - self.linking = set() - - self.add_events(gtk.gdk.POINTER_MOTION_HINT_MASK) - self.add_events(gtk.gdk.LEAVE_NOTIFY_MASK) - - self.connect('populate-popup', TextOutput.popup) - self.connect('motion-notify-event', TextOutput.hover) - self.connect('button-press-event', TextOutput.mousedown) - self.connect('button-release-event', TextOutput.mouseup) - self.connect_after('button-release-event', lambda *a: True) - self.connect('leave-notify-event', TextOutput.clear_hover) - - self.hover_coords = 0, 0 - - self.autoscroll = True - self._scrolling = False - self.scroller = gtk.Adjustment() - - def setup_scroll(self, _adj, vadj): - self.scroller = vadj - - if vadj: - def set_scroll(adj): - self.autoscroll = adj.value + adj.page_size >= adj.upper - - vadj.connect("value-changed", set_scroll) - - self.connect("set-scroll-adjustments", setup_scroll) - self.connect("size-allocate", TextOutput.scroll) - - def set_cursor(widget): - self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(None) - - self.connect("realize", set_cursor) - - style_me(self, "view") - -class WindowLabel(gtk.EventBox): - def update(self): - title = self.win.get_title() - - for escapes in (('&','&'), ('<','<'), ('>','>')): - title = title.replace(*escapes) - - for a_type in (HILIT, TEXT, EVENT): - if a_type in self.win.activity: - title = ACTIVITY_MARKUP[a_type] % title - break - - self.label.set_markup(title) - - def tab_popup(self, event): - if event.button == 3: # right click - c_data = self.events.data(window=self.win, menu=[]) - self.events.trigger("WindowMenu", c_data) - - c_data.menu += [ - None, - ("Close", gtk.STOCK_CLOSE, self.win.close), - ] - - menu = gtk.Menu() - for item in menu_from_list(c_data.menu): - menu.append(item) - menu.show_all() - menu.popup(None, None, None, event.button, event.time) - - def __init__(self, window, core): - gtk.EventBox.__init__(self) - self.core = core - self.events = core.events - - self.win = window - self.connect("button-press-event", WindowLabel.tab_popup) - - self.label = gtk.Label() - self.add(self.label) - - self.update() - self.show_all() - -class FindBox(gtk.HBox): - def remove(self, *args): - self.parent.remove(self) - self.win.focus() - - def clicked(self, button, search_down=False): - text = self.textbox.get_text() - - if not text: - return - - buffer = self.win.output.get_buffer() - - if buffer.get_selection_bounds(): - if button == self.down: - _, cursor_iter = buffer.get_selection_bounds() - else: - cursor_iter, _ = buffer.get_selection_bounds() - else: - cursor_iter = buffer.get_end_iter() - - if search_down: - cursor = cursor_iter.forward_search( - text, gtk.TEXT_SEARCH_VISIBLE_ONLY - ) - else: - cursor = cursor_iter.backward_search( - text, gtk.TEXT_SEARCH_VISIBLE_ONLY - ) - - if not cursor: - return - - fr, to = cursor - - if button == self.up: - buffer.place_cursor(fr) - self.win.output.scroll_to_iter(fr, 0) - elif button == self.down: - buffer.place_cursor(to) - self.win.output.scroll_to_iter(to, 0) - - buffer.select_range(*cursor) - - cursor_iter = buffer.get_iter_at_mark(buffer.get_insert()) - - def __init__(self, window): - gtk.HBox.__init__(self) - - self.win = window - - self.up = gtk.Button(stock='gtk-go-up') - self.down = gtk.Button(stock='gtk-go-down') - - self.up.connect('clicked', self.clicked) - self.down.connect('clicked', self.clicked, True) - - self.up.set_property('can_focus', False) - self.down.set_property('can_focus', False) - - self.textbox = gtk.Entry() - - self.textbox.connect('focus-out-event', self.remove) - self.textbox.connect('activate', self.clicked) - - self.pack_start(gtk.Label('Find:'), expand=False) - self.pack_start(self.textbox) - - self.pack_start(self.up, expand=False) - self.pack_start(self.down, expand=False) - - self.show_all() - -#class UrkUITabs(gtk.Window): -class UrkUITabs(object): - def __init__(self, core): - # threading stuff - gtk.gdk.threads_init() - self.core = core - self.events = core.events - self.tabs = gtk.Notebook() - self.tabs.set_property( - "tab-pos", - conf.get("ui-gtk/tab-pos", gtk.POS_BOTTOM) - ) - - self.tabs.set_scrollable(True) - self.tabs.set_property("can-focus", False) - - self.box = gtk.VBox(False) - self.box.pack_end(self.tabs) - - def __iter__(self): - return iter(self.tabs.get_children()) - - def __len__(self): - return self.tabs.get_n_pages() - - def exit(self, *args): - self.events.trigger("Exit") - gtk.main_level() and gtk.main_quit() - - def get_active(self): - return self.tabs.get_nth_page(self.tabs.get_current_page()) - - def set_active(self, window): - self.tabs.set_current_page(self.tabs.page_num(window)) - - def add(self, window): - for pos in reversed(range(self.tabs.get_n_pages())): - if self.tabs.get_nth_page(pos).network == window.network: - break - else: - pos = self.tabs.get_n_pages() - 1 - - self.tabs.insert_page(window, WindowLabel(window, self.core), pos+1) - - def remove(self, window): - self.tabs.remove_page(self.tabs.page_num(window)) - - def update(self, window): - self.tabs.get_tab_label(window).update() - - def show_all(self): - self.box.show_all() diff --git a/services/console/lib/purk/windows.py b/services/console/lib/purk/windows.py deleted file mode 100644 index 22c783aa..00000000 --- a/services/console/lib/purk/windows.py +++ /dev/null @@ -1,298 +0,0 @@ -import gtk - -import irc -from conf import conf -import widgets - -#manager = widgets.UrkUITabs() - -def append(window, manager): - manager.add(window) - -def remove(window, manager): - manager.remove(window) - - # i don't want to have to call this - window.destroy() - -def new(wclass, network, id, core): - if network is None: - network = irc.dummy_network - - w = get(wclass, network, id, core) - if not w: - w = wclass(network, id, core) - append(w, core.manager) - - return w - -def get(windowclass, network, id, core): - if network: - id = network.norm_case(id) - - for w in core.manager: - if (type(w), w.network, w.id) == (windowclass, network, id): - return w - -def get_with(manager, wclass=None, network=None, id=None): - if network and id: - id = network.norm_case(id) - - for w in list(manager): - for to_find, found in ((wclass, type(w)), (network, w.network), (id, w.id)): - # to_find might be False but not None (if it's a DummyNetwork) - if to_find is not None and to_find != found: - break - else: - yield w - -def get_default(network, manager): - - window = manager.get_active() - if window.network == network: - return window - - # There can be only one... - for window in get_with(network=network): - return window - -class Window(gtk.VBox): - need_vbox_init = True - - def mutate(self, newclass, network, id): - isactive = self == manager.get_active() - self.hide() - - for child in self.get_children(): - self.remove(child) - - self.__class__ = newclass - self.__init__(network, id) - self.update() - if isactive: - self.activate() - - def transfer_text(self, _widget, event): - if event.string and not self.input.is_focus(): - self.input.grab_focus() - self.input.set_position(-1) - self.input.event(event) - - def write(self, text, activity_type=widgets.EVENT, line_ending='\n', fg=None): - if self.manager.get_active() != self: - self.activity = activity_type - self.output.write(text, line_ending, fg) - - def get_id(self): - if self.network: - return self.network.norm_case(self.rawid) - else: - return self.rawid - - def set_id(self, id): - self.rawid = id - self.update() - - id = property(get_id, set_id) - - def get_toplevel_title(self): - return self.rawid - - def get_title(self): - return self.rawid - - def get_activity(self): - return self.__activity - - def set_activity(self, value): - if value: - self.__activity.add(value) - else: - self.__activity = set() - self.update() - - activity = property(get_activity, set_activity) - - def focus(self): - pass - - def activate(self): - self.manager.set_active(self) - self.focus() - - def close(self): - self.events.trigger("Close", window=self) - remove(self, self.manager) - - def update(self): - self.manager.update(self) - - def __init__(self, network, id, core): - self.manager = core.manager - self.events = core.events - - if self.need_vbox_init: - #make sure we don't call this an extra time when mutating - gtk.VBox.__init__(self, False) - self.need_vbox_init = False - - if hasattr(self, "buffer"): - self.output = widgets.TextOutput(core, self, self.buffer) - else: - self.output = widgets.TextOutput(core, self) - self.buffer = self.output.get_buffer() - - if hasattr(self, "input"): - if self.input.parent: - self.input.parent.remove(self.input) - else: - self.input = widgets.TextInput(self, core) - - self.network = network - self.rawid = id - - self.__activity = set() - -class SimpleWindow(Window): - def __init__(self, network, id, core): - Window.__init__(self, network, id) - - self.focus = self.input.grab_focus - self.connect("key-press-event", self.transfer_text) - - self.pack_end(self.input, expand=False) - - topbox = gtk.ScrolledWindow() - topbox.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - topbox.add(self.output) - - self.pack_end(topbox) - - self.show_all() - -class StatusWindow(Window): - def get_toplevel_title(self): - return '%s - %s' % (self.network.me, self.get_title()) - - def get_title(self): - # Something about self.network.isupport - if self.network.status: - return "%s" % self.network.server - else: - return "[%s]" % self.network.server - - def __init__(self, network, id, core): - Window.__init__(self, network, id, core) - - self.nick_label = widgets.NickEditor(self, core) - - self.focus = self.input.grab_focus - self.connect("key-press-event", self.transfer_text) - self.manager = core.manager - botbox = gtk.HBox() - botbox.pack_start(self.input) - botbox.pack_end(self.nick_label, expand=False) - - self.pack_end(botbox, expand=False) - - topbox = gtk.ScrolledWindow() - topbox.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - topbox.add(self.output) - - self.pack_end(topbox) - - self.show_all() - -class QueryWindow(Window): - def __init__(self, network, id, core): - Window.__init__(self, network, id, core) - - self.nick_label = widgets.NickEditor(self, core) - - self.focus = self.input.grab_focus - self.connect("key-press-event", self.transfer_text) - - botbox = gtk.HBox() - botbox.pack_start(self.input) - botbox.pack_end(self.nick_label, expand=False) - - self.pack_end(botbox, expand=False) - - topbox = gtk.ScrolledWindow() - topbox.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - topbox.add(self.output) - - self.pack_end(topbox) - - self.show_all() - -def move_nicklist(paned, event): - paned._moving = ( - event.type == gtk.gdk._2BUTTON_PRESS, - paned.get_position() - ) - -def drop_nicklist(paned, event): - width = paned.allocation.width - pos = paned.get_position() - - double_click, nicklist_pos = paned._moving - - if double_click: - # if we're "hidden", then we want to unhide - if width - pos <= 10: - # get the normal nicklist width - conf_nicklist = conf.get("ui-gtk/nicklist-width", 200) - - # if the normal nicklist width is "hidden", then ignore it - if conf_nicklist <= 10: - paned.set_position(width - 200) - else: - paned.set_position(width - conf_nicklist) - - # else we hide - else: - paned.set_position(width) - - else: - if pos != nicklist_pos: - conf["ui-gtk/nicklist-width"] = width - pos - 6 - -class ChannelWindow(Window): - def __init__(self, network, id, core): - Window.__init__(self, network, id, core) - - self.nicklist = widgets.Nicklist(self, core) - self.nick_label = widgets.NickEditor(self, core) - - self.focus = self.input.grab_focus - self.connect("key-press-event", self.transfer_text) - - topbox = gtk.ScrolledWindow() - topbox.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - topbox.add(self.output) - - nlbox = gtk.ScrolledWindow() - nlbox.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - nlbox.add(self.nicklist) - - nlbox.set_size_request(conf.get("ui-gtk/nicklist-width", 112), -1) - - botbox = gtk.HBox() - botbox.pack_start(self.input) - botbox.pack_end(self.nick_label, expand=False) - - self.pack_end(botbox, expand=False) - - pane = gtk.HPaned() - pane.pack1(topbox, resize=True, shrink=False) - pane.pack2(nlbox, resize=False, shrink=True) - - self.nicklist.pos = None - - pane.connect("button-press-event", move_nicklist) - pane.connect("button-release-event", drop_nicklist) - - self.pack_end(pane) - - self.show_all()