├── .gitignore ├── CHANGES.txt ├── README.txt ├── TODO.txt ├── docs └── vision.html ├── howie.ini ├── howie.nsi ├── howie ├── __init__.py ├── aiml │ ├── AimlParser.py │ ├── DefaultSubs.py │ ├── Kernel.py │ ├── PatternMgr.py │ ├── Utils.py │ ├── WordSub.py │ ├── __init__.py │ └── self-test.aiml ├── configFile.py ├── core.py └── frontends │ ├── __init__.py │ ├── aim.py │ ├── frontend.py │ ├── icq.py │ ├── irc.py │ ├── ircbot.py │ ├── irclib.py │ ├── jabber.py │ ├── msn.py │ ├── msnp │ ├── __init__.py │ ├── chat.py │ ├── codec.py │ ├── command.py │ ├── error.py │ ├── friend.py │ ├── net.py │ ├── protocol.py │ └── session.py │ ├── oscarlistener.py │ ├── tty.py │ ├── xmlrpc.py │ └── xmpp │ ├── __init__.py │ ├── auth.py │ ├── browser.py │ ├── client.py │ ├── debug.py │ ├── dispatcher.py │ ├── features.py │ ├── filetransfer.py │ ├── protocol.py │ ├── roster.py │ ├── session.py │ ├── simplexml.py │ └── transports.py ├── make_win32_installer.bat ├── my-howie.aiml ├── runme.py ├── scripts ├── acronym.py ├── echo.py ├── googlism.py ├── multiple.db ├── rhyme.py ├── rhymes.db └── words.db ├── setup.cfg ├── setup.py ├── standard ├── _readme.txt ├── dev-calendar.aiml ├── dev-examples.aiml ├── dev-scripts.aiml ├── dev-testcases.aiml ├── dev-translation.aiml ├── dev-webhelper.aiml ├── howie-acronym.aiml ├── howie-googlism.aiml ├── howie-rhyme.aiml ├── per-drWallace.aiml ├── startup.xml ├── std-65percent.aiml ├── std-atomic.aiml ├── std-botmaster.aiml ├── std-brain.aiml ├── std-connect.aiml ├── std-dictionary.aiml ├── std-disconnect.aiml ├── std-dont.aiml ├── std-errors.aiml ├── std-gender.aiml ├── std-geography.aiml ├── std-german.aiml ├── std-gossip.aiml ├── std-hello.aiml ├── std-inactivity.aiml ├── std-inventions.aiml ├── std-knowledge.aiml ├── std-lizards.aiml ├── std-login.aiml ├── std-numbers.aiml ├── std-personality.aiml ├── std-pickup.aiml ├── std-politics.aiml ├── std-profile.aiml ├── std-religion.aiml ├── std-robot.aiml ├── std-sales.aiml ├── std-sextalk.aiml ├── std-sports.aiml ├── std-srai.aiml ├── std-suffixes.aiml ├── std-that.aiml ├── std-turing.aiml └── std-yesno.aiml ├── std-startup.xml └── unix-install.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | - SF Bug #1050427: Howie now reliably disconnects and quits when you give him 2 | a control-C. 3 | - Upgraded to PyAIML version 0.8.5. This version includes standards-compliant 4 | whitespace handling, and fixes a handful of Unicode and crash bugs. 5 | - AIM/ICQ: Updated for compatibility with Twisted 2.2.0 (removed some deprecation warnings). 6 | - JABBER: Upgraded to xmpppy 0.3.1. 7 | - JABBER: Removed hard-coded port number, and put it in howie.ini instead. 8 | 9 | 0.6.0: 10 | - Upgraded to PyAIML version 0.8.4. This version includes support for 11 | multiple wildcards in AIML patterns, the "index" attribute of the "star" 12 | AIML elements, and Unicode input and AIML files. 13 | - Improved error-handling during front-end module initialization. Previously, 14 | any errors were mistakenly reported as "could not find valid frontend class" 15 | warnings. 16 | - AIM: Replaced broken PyTOC module with Twisted's OSCAR module. 17 | - ICQ: Added support for the ICQ protocol. 18 | - IRC: Added support for the IRC protocol (courtesy of Jamie Turner). 19 | - JABBER: Modified jabber back-end to use the xmpppy package, instead of the 20 | apparently-defunct jabber.py. 21 | - MSN: Applied patch to msnp module to fix problem with redirect messages 22 | while logging in. 23 | - MSN: Fixed bug in msnp's __process_add() function. 24 | - MSN: Fixed bug in MSN frontend's friend-adding code. 25 | - XMLRPC: Wrapped call to register_introspection_functions() to allow it to 26 | run without crashing older versions of Python. 27 | 28 | 29 | 0.5.0: 30 | - Arbitrary switch from date-based snapshots to "real" version numbers 31 | - Upgraded AIML interpreter to PyAIML version 0.8.2. This release fixes some 32 | crashes involving infinite AIML recursion and passing Unicode strings as 33 | input to the bot. 34 | - Upgraded to MSNP 0.4.1. The MSN front-end is now working! I'll continue to 35 | improve it in future releases, but it should be quite usable for now. 36 | - Added Jabber chat front-end (based on jabber.py by Matthew Allum). 37 | - Added new "botinfo" section to the config file, used to customize your bot's 38 | personality. Any entries added to this section are used to set up the 39 | bot predicates (accessed through the AIML element). 40 | 41 | 1/10/2004: 42 | - Upgraded AIML interpreter to PyAIML version 0.8.1. Fixes a problem with 43 | "system" tags written for Windows not working on UNIX, and vice versa. For 44 | cross-platform compatibility, all "system" tags should use UNIX-style 45 | pathnames (e.g. "path/to/script"). 46 | - Added "unix-install.py" helper script to automate some necessary setup 47 | steps on UNIX platforms. 48 | - Removed some Python 2.3-specific features; Howie should now run on Python 49 | 2.2.x. 50 | - Howie now prompts for screenname/password at startup if the values aren't 51 | specified in the config file (useful for those who don't like leaving 52 | passwords lying around in plaintext on disk). 53 | - Reorganized and commented configuration file. 54 | 55 | 1/9/2004: 56 | - Upgraded AIML interpreter to PyAIML version 0.8. 57 | - Upgraded msnp package to v0.4.0 (the frontend still doesn't work, though). 58 | - Added XMLRPC front-end. 59 | - Added support for "what does X stand for" questions (acronym expansion). 60 | - Added support for persistent session data (so Howie remembers the people 61 | he's talked to even after he's rebooted). To enable, set "sessionspersist" 62 | to "yes" in howie.ini. 63 | 64 | 12/17/2003: 65 | - New pure-Python AIML interpreter (out with J-Alice, in with PyAIML, 66 | version 0.5). 67 | - Fixed minor bugs in Googlism code. 68 | - Added some missing tags in AIML files. 69 | - Bot name and verbosity are now initialized from the config file. 70 | - Added support for conversation logging (enabled in the config file). 71 | - Howie can now answer "what rhymes with X?" questions. 72 | - Installer now lets you customize which optional extension modules are 73 | installed. 74 | 75 | 12/1/2003: "Apocalypse Howie (Dev-20031201) is released 76 | - Fixed bug in front-end loader that required a bunch of otherwise 77 | unnecessary Python scripts to be included with a binary installation. 78 | - Fixed broken sync-mode tags on Win32 builds! This is huge -- 79 | sync-mode tags will be the keystone of Howie's future 80 | functionality. 81 | - Added a "scripts" directory, as a repository for the add-on commands 82 | that Howie will run from inside tags. 83 | - Added a "my-howie.aiml" file for users to fill with their own custom AIML 84 | responses. 85 | - Moved Googlisms back-end into a stand-alone Python script, triggered through 86 | AIML using a sync-mode tag. This is the future! 87 | 88 | 11/21/2003: "Return of the Howie Extended Edition" (Dev-20031121) is released 89 | - Windows binary distribution is now a self-contained executable. 90 | On Windows systems, Python is no longer required to run Howie. 91 | - Added documentation folder, mostly pertaining to compiling the sources. 92 | 93 | 11/19/2003: "Return Of The Howie" (Dev-20031119) is released 94 | - Updated J-Alice to version 0.5. See the J-Alice homepage for summary 95 | of new features. 96 | 97 | 5/30/2003: "Finding Howie" (Dev-20030530) is released 98 | - Fixed J-Alice bug which caused Howie to repeat his first response 99 | over and over. 100 | - Massive code reorganization makes adding new frontends a breeze! 101 | - Connection parameters are read from the new configuration file, 102 | howie.ini. 103 | - Added command-line interface (force command-line only with the -l flag). 104 | 105 | 5/15/2003: "Howie Reloaded" (Dev-20030515) is released 106 | - initial pre-pre-alpha version, Windows installer only. 107 | - AIM only 108 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Howie - A Conversational AI Bot 2 | (http://howie.sourceforge.net/) 3 | Copyright (C) 2003-2004 Cort Stratton (cortATcortstrattonDOTorg) 4 | 5 | ABOUT HOWIE 6 | ----------- 7 | Howie is a conversational AI -- a computer program you can talk to. He 8 | is designed to be simple to install, configure and (above all) extend. 9 | 10 | Howie is Friendly. 11 | Currently, Howie is willing to discuss religion, sports, sex (reluctantly), 12 | and philosophy. He even knows a little German! 13 | 14 | Howie is Helpful. 15 | Howie is able to answer most questions of the form "Who/what/where/when 16 | is/was/are/were X?" -- though his answers are occasionally more 17 | entertaining than accurate. He can also help find rhymes for a word, or 18 | tell you what an acronym means. He will someday provide definitions or 19 | synonyms for any word in the dictionary, query your address book, and even 20 | perform a few simple remote system-administration tasks! 21 | 22 | Howie is Connected. 23 | You can communicate with Howie in a number of different ways: AIM, ICQ, IRC, MSN 24 | Messenger, Jabber Chat, XML-RPC, or locally on the command-line. Future 25 | versions will include interfaces for HTTP, Zephyr, and more! 26 | Howie's knowledge base is made up of a wide variety of Internet resources. 27 | If you find something that he can't do, it's usually pretty 28 | straightforward to teach him! 29 | 30 | SYSTEM REQUIREMENTS 31 | ------------------- 32 | Howie has been tested on Windows XP, Red Hat Linux and NetBSD. However, 33 | he should work on any system that meets the following requirements: 34 | - Python 2.2.x or greater. 35 | - 64 MB available RAM (depending on the AIML set you're using) 36 | - Dedicated Internet connection 37 | - The Twisted framework, version 2.2.0 or later (http://twistedmatrix.com/products/twisted). 38 | You must have Twisted installed in order to run Howie from the source. 39 | NOTE: The Windows binary distribution already includes Twisted. 40 | 41 | NOTE: There is a known problem with Howie running under Windows 95, having 42 | to do with Python's os.popen() function not working on that platform. 43 | 44 | INSTALLATION (Windows binary distribution) 45 | ------------------------------------------ 46 | 1. Run the installer (you've done that). 47 | 2. Edit the howie.ini file, found in the directory where you installed Howie. 48 | (You can access this file through the "Howie->Configure Howie" shortcut in 49 | your Start Menu). This file lets you set up the interfaces presented to 50 | visitors (AIM, MSN, etc.) as well as customize Howie's behavior. Each 51 | section has an "active" parameter, which indicates whether that module is 52 | active ("yes") or not. 53 | 3. To test Howie in local-mode (text console interface only), use the 54 | "Howie->Run Howie (local)" shortcut in your Start Menu. This will let you 55 | chat with Howie without opening any connections to the Internet. 56 | 4. Once you're satisfied with your setup, run the "Howie->Run Howie" shortcut, 57 | found in your Start Menu. This launches Howie and makes him available to 58 | world at large! 59 | 60 | INSTALLATION (Source distribution) 61 | ---------------------------------- 62 | 1. Unzip the archive (you've done that). 63 | 2. UNIX USERS: run the "unix-install.py" script found in the main Howie 64 | directory (run "python unix-install.py" from the main Howie directory). 65 | It will automatically configure Howie to run in a UNIX-like environment. 66 | 3. Edit the howie.ini file, found in the directory where you installed Howie. 67 | This file lets you set up the interfaces presented to visitors (AIM, MSN, 68 | etc.) as well as customize Howie's behavior. Each section has an "active" 69 | parameter, which indicates whether that module is active ("yes") or not. 70 | 4. To test Howie locally, run "runme.py -l" in the main Howie directory. 71 | This lets you chat with Howie without activating any of his network 72 | services. 73 | 5. Once you're satisfied with your setup, run "runme.py" in the main Howie 74 | directory. This launches Howie and makes him available to the world at 75 | large! 76 | 77 | ACKNOWLEDGEMENTS 78 | ---------------- 79 | The Win32 installer was produced using the Nullsoft Install System 80 | (http://www.nullsoft.com/free/nsis/). 81 | 82 | The Win32 binary distribution is made possible thanks to py2exe 83 | (http://starship.python.net/crew/theller/py2exe/). 84 | 85 | Howie's conversational back-end is provided by PyAIML 86 | (http://pyaiml.sourceforge.net), a Python implementation of Dr. Richard S. 87 | Wallace's A.L.I.C.E. system. For more information about the A.L.I.C.E. 88 | Foundation (including information on AIML, the Artificial Intelligence 89 | Markup Language used to program Howie's responses), visit the A.L.I.C.E. 90 | homepage at http://www.alicebot.org/. 91 | 92 | Howie's AIM and ICQ front-ends are provided by Twisted 93 | (http://twistedmatrix.com/products/twisted). 94 | 95 | Howie's IRC front-end was written by Jamie Turner (author of Py-TOC), and is 96 | built on top of Joel Rosdahl's Python IRC library 97 | (http://python-irclib.sourceforge.net/). 98 | 99 | Howie's MSN front-end is provided by msnp, a Python MSN module by Manish 100 | Jethani (http://msnp.sourceforge.net/). 101 | 102 | Howie's Jabber front-end is provided by xmpppy (http://xmpppy.sourceforge.net). 103 | 104 | Howie is named after Howie Day (http://www.howieday.com/), for no particular 105 | reason. If it weren't for Amy Kalson, he would be named something truly boring 106 | like PyBot or PyBorg. 107 | 108 | Hooray for Python! (http://www.python.org/) -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | Additional frontends: 2 | - WEB: In progress. 3 | 4 | Additional extension modules: 5 | - Email spoofer. 6 | - Address book / contact manager 7 | - Sysadmin assistant 8 | 9 | Other features: 10 | - Auto-configuration tool (script, GUI) 11 | - Add the ability to initiate a chat session (either when a buddy logs in, or 12 | at the request of another buddy (e.g. "Hey, you should talk to SoAndSo"). 13 | This will be easy in AIM, difficult in MSN (ask Mannu), and pretty much 14 | impossible in web/XMLRPC. -------------------------------------------------------------------------------- /docs/vision.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My Vision For Howie 5 | 6 | 7 | 8 |

My Vision For Howie

9 |

Cort Stratton (cort@users.sourceforge.net)

10 | 11 |

A Brief History Of Conversational AI

12 | 13 |

The Turing 15 | Test was proposed by legendary computer science pioneer Alan 16 | Turing as a way of measuring the intelligence of a computer 17 | program. Basically, the test challenges an artifical intelligence 18 | program to convince a human judge that it is human. The Turing 19 | Test was fiirst proposed in 1950, and despite a half-century of 20 | progress in the field of Artificial Intelligence, not a single 21 | program has ever passed it.

22 | 23 |

Nevertheless, people keep trying. Every year, a handful of the 24 | world's best conversational AI programs square off in the Loebner 26 | Prize Content (basically a formalized Turing Test, with a 27 | grand prize of US$100,000 to the first program to fool the human 28 | judges). However, after looking at the results 30 | of the 2003 Loebner Prize Contest, it's clear that 31 | conversational AI programs have a long way to go before they have 32 | any hope of passing as humans.

33 | 34 |

Several of the "best" Loebner entries are available on the Web. 35 | You can test your conversational mettle against MegaHAL, Eliza, 38 | or A.L.I.C.E. (the closest 39 | thing Howie has to a mother).

40 | 41 |

Proud To Flunk The Turing Test!

42 | 43 |

After conversing with a few chatterbots, or reading over 44 | conversational transcripts, one begins to notice a pattern: 45 | computers really aren't that interesting to talk to. Most 46 | conversations start out innocently enough, exchanging pleasantries 47 | and such. Before too long, however, the conversation devolves 48 | into one of the following scenarios: 49 | 50 |

    51 | 52 |
  • The human begins propositioning the computer for sex. This 53 | behavior is so universally predictable that most chatterbots are 54 | actually quite comfortable with the topic. (Try this with 55 | A.L.I.C.E., incidentally).
  • 56 | 57 |
  • The computer suffers a logic error, and spits out a non 58 | sequitor. Depending on how interesting/humorous the 59 | computer's response is, the human continues to feed in 60 | increasingly nonsensical input, curious to see how the program 61 | will respond.
  • 62 | 63 |
  • The program suffers from severe short-term memory loss (an 64 | affliction which is sadly widespread in modern conversational 65 | AIs), and becomes unable to remember anything further back than 66 | the most recent human statement. The conversation quickly 67 | becomes a stream of content-free conversational no-ops 68 | (e.g. "Ah, I understand.", "You do?", "Yes.", "Good.", "You are 69 | pleased?", "Yes.", "Excellent.", "Thank you.", "You're 70 | welcome!", "Don't mention it.", and so on). Eventually, the 71 | human loses interest.

    72 | 73 |
74 | 75 |

In short, you aren't going to see Howie entering the Loebner 76 | Prize Contest any time soon. Howie is proud to stand and be 77 | counted among the losers!

78 | 79 |

A New Frontier in Human-Computer Interaction

80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /howie.ini: -------------------------------------------------------------------------------- 1 | # Brief description of general options: 2 | # ------------------------------------- 3 | # logging: should the bot keep logs of all conversatons [yes/no] 4 | # logdir: if logging is enabled, which directory should the logs be kept in? 5 | # maxdelay: maximum artificial delay (in seconds) between responses. Used 6 | # to make the bot seem more human. 7 | # sessionspersist: Should the bot use persistent sessions? (basically, should 8 | # it remember what it learns about its visitors if the bot 9 | # is restarted? [yes/no] 10 | # sessionsdir: If persistent sessions are enabled, which directory should the 11 | # session data be saved to? 12 | # verbose: Should the bot print extra debugging information [yes/no] 13 | [general] 14 | logging = no 15 | logdir = logs 16 | maxdelay = 0 17 | sessionspersist = no 18 | sessionsdir = sessions 19 | verbose = no 20 | 21 | # 22 | # Bot Information. This is where you describe your bot. 23 | # Any entries in this section will be available through the AIML 24 | # element, where XXX is the name of the entry. 25 | # For example, will evaluate to whatever you 26 | # enter for the value of "master" below ("Your Name" by default). 27 | # 28 | # You may add as many entries as you'd like to this section. Give 29 | # your bot a favoritemovie, a hometown or a significantother! 30 | # 31 | [botinfo] 32 | name = Howie 33 | master = Your Name 34 | 35 | # 36 | # Front-end-specific options follow. Each section has an "active" option 37 | # which indicates whether that front-end should be enabled or not [yes/no]. 38 | # 39 | # NOTE: All screenname/password fields can be left blank, in which case 40 | # Howie will prompt for the necessary information at startup. 41 | # 42 | 43 | # The AOL Instant Messenger interface. 44 | [aim] 45 | active = no 46 | screenname = 47 | password = 48 | profile = Bot's profile goes here. 49 | 50 | # The ICQ interface. 51 | [icq] 52 | active = no 53 | screenname = 54 | password = 55 | profile = Bot's profile goes here. 56 | 57 | # The IRC interface 58 | [irc] 59 | active = no 60 | server = 61 | port = 6667 62 | nick = 63 | channel = 64 | 65 | # The Jabber chat interface. By default, Howie attempts to connect through 66 | # port 5223 using a secure SSL connection; if your server does not support 67 | # SSL, you should change the port number below to 5222. 68 | [jabber] 69 | active = no 70 | username = 71 | password = 72 | server = jabber.org 73 | port = 5223 74 | resource = default 75 | nickname = Howie 76 | 77 | # The MSN Messenger interface 78 | [msn] 79 | active = no 80 | screenname = 81 | password = 82 | displayname = Howie 83 | 84 | # The local TTY (text console) interface. 85 | [tty] 86 | active = yes 87 | 88 | # The XML-RPC interface. 89 | # This interface serves a single function: respond(input,sessionID). 90 | # The "input" parameter contains the user's input, and the "user" parameter 91 | # contains the unique session identifier string (usually the user's name). 92 | # It returns the bot's response. 93 | [xmlrpc] 94 | active = no 95 | port = 8000 96 | -------------------------------------------------------------------------------- /howie.nsi: -------------------------------------------------------------------------------- 1 | # howie.nsi 2 | # 3 | # Author: Cort Stratton (cortATcortstrattonDOTorg) 4 | # 5 | 6 | !include "MUI.nsh" 7 | 8 | #-------------------------------- 9 | #Configuration 10 | 11 | # Basic definitions 12 | Var MY_PRODUCT 13 | Var MY_VERSION 14 | !define MY_PRODUCT "Howie" 15 | !define MY_VERSION "0.6.0" 16 | 17 | # General 18 | Name "${MY_PRODUCT}" 19 | OutFile "..\dist\howie-install-${MY_VERSION}.exe" 20 | 21 | # Folder selection page 22 | InstallDir "$PROGRAMFILES\${MY_PRODUCT}" 23 | InstallDirRegKey HKLM "Software\${MY_PRODUCT}" "Install_Dir" 24 | 25 | # MUI stuff 26 | Var MUI_TEMP 27 | Var STARTMENU_FOLDER 28 | 29 | # Compiler configuration 30 | SetCompressor bzip2 31 | ShowInstDetails show 32 | ShowUninstDetails show 33 | InstProgressFlags smooth colored 34 | XPStyle on 35 | 36 | #-------------------------------- 37 | #Modern UI Configuration 38 | 39 | !insertmacro MUI_PAGE_COMPONENTS 40 | !insertmacro MUI_PAGE_DIRECTORY 41 | !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" 42 | !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\${MY_PRODUCT}" 43 | !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" 44 | !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER 45 | !insertmacro MUI_PAGE_INSTFILES 46 | !define MUI_FINISHPAGE_RUN_NOTCHECKED 47 | !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\README.txt" 48 | !define MUI_FINISHPAGE_NOREBOOTSUPPORT 49 | !insertmacro MUI_PAGE_FINISH 50 | 51 | !define MUI_ABORTWARNING 52 | 53 | !insertmacro MUI_UNPAGE_CONFIRM 54 | !insertmacro MUI_UNPAGE_INSTFILES 55 | 56 | #-------------------------------- 57 | #Languages 58 | 59 | !insertmacro MUI_LANGUAGE "English" 60 | 61 | #-------------------------------- 62 | #Language Strings 63 | 64 | # Description 65 | LangString DESC_SecCopyMain ${LANG_ENGLISH} "Installs ${MY_PRODUCT} files to the application folder." 66 | LangString DESC_SecCopyAddOns ${LANG_ENGLISH} "Installs some optional add-on modules to extend ${MY_PRODUCT}'s capabilities." 67 | LangString DESC_SecCopyAcronym ${LANG_ENGLISH} "Handles 'what does X stand for' questions." 68 | LangString DESC_SecCopyGooglism ${LANG_ENGLISH} "Handles 'who/what/where/when is X' questions." 69 | LangString DESC_SecCopyRhyme ${LANG_ENGLISH} "Handles 'what rhymes with X' questions." 70 | 71 | #-------------------------------- 72 | #Reserve Files 73 | 74 | # Things that need to be extracted on first (keep these lines before any 75 | # File command!). Only useful for BZIP2 compression. 76 | !insertmacro MUI_RESERVEFILE_LANGDLL 77 | 78 | #-------------------------------- 79 | #Installer Sections 80 | 81 | Section "!${MY_PRODUCT} (required)" SecCopyMain 82 | # Indicate that this section should always be installed. 83 | SectionIn RO 84 | 85 | # Set output path to the installation directory. 86 | SetOutPath $INSTDIR 87 | 88 | # Install core files. 89 | DetailPrint "Installing core files..." 90 | SetDetailsPrint textonly 91 | File /r dist\* 92 | Rename runme.exe howie.exe 93 | SetDetailsPrint both 94 | 95 | # Install documentation 96 | DetailPrint "Installing documentation..." 97 | SetDetailsPrint textonly 98 | SetOutPath $INSTDIR\docs 99 | File /r docs\*.html 100 | SetDetailsPrint both 101 | 102 | # Install uninstaller program 103 | DetailPrint "Installing uninstaller..." 104 | SetDetailsPrint textonly 105 | SetOutPath $INSTDIR 106 | WriteUninstaller Uninstall.exe 107 | WriteRegStr HKLM \ 108 | "Software\Microsoft\Windows\CurrentVersion\Uninstall\${MY_PRODUCT}" \ 109 | "DisplayName" "Howie ${MY_VERSION} (remove only)" 110 | WriteRegStr HKLM \ 111 | "Software\Microsoft\Windows\CurrentVersion\Uninstall\${MY_PRODUCT}" \ 112 | "UninstallString" "$INSTDIR\Uninstall.exe" 113 | WriteRegDWORD HKLM \ 114 | "Software\Microsoft\Windows\CurrentVersion\Uninstall\${MY_PRODUCT}" \ 115 | "NoModify" 1 116 | WriteRegDWORD HKLM \ 117 | "Software\Microsoft\Windows\CurrentVersion\Uninstall\${MY_PRODUCT}" \ 118 | "NoRepair" 1 119 | WriteRegStr HKLM "Software\${MY_PRODUCT}" "Installer Language" $LANGUAGE 120 | SetDetailsPrint both 121 | 122 | # Write Start Menu shortcuts 123 | !insertmacro MUI_STARTMENU_WRITE_BEGIN Application 124 | # Create shortcuts 125 | DetailPrint "Installing Start Menu shortcuts..." 126 | SetDetailsPrint textonly 127 | CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" 128 | SetOutPath $INSTDIR # To set working directory for shortcut 129 | CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Configure ${MY_PRODUCT}.lnk" \ 130 | "$INSTDIR\howie.ini" 131 | CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Run ${MY_PRODUCT}.lnk" \ 132 | "$INSTDIR\howie.exe" 133 | CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Run ${MY_PRODUCT} (Local Mode).lnk" \ 134 | "$INSTDIR\howie.exe" "-l" 135 | CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall ${MY_PRODUCT}.lnk" \ 136 | "$INSTDIR\Uninstall.exe" 137 | CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\README.lnk" \ 138 | "$INSTDIR\README.txt" 139 | 140 | # Write shortcut location to the registry (for Uninstaller) 141 | WriteRegStr HKLM "Software\${MY_PRODUCT}" "Start Menu Folder" "$STARTMENU_FOLDER" 142 | SetDetailsPrint both 143 | !insertmacro MUI_STARTMENU_WRITE_END 144 | SectionEnd 145 | 146 | SubSection "Add-ons" SecCopyAddOns 147 | Section "Acronyms" SecCopyAcronym 148 | # Install acronym 149 | DetailPrint "Installing Acronym module..." 150 | SetDetailsPrint textonly 151 | SetOutPath $INSTDIR\scripts 152 | File scripts\acronym.py 153 | SetOutPath $INSTDIR\standard 154 | File standard\howie-acronym.aiml 155 | SetDetailsPrint both 156 | SectionEnd 157 | 158 | Section "Googlisms" SecCopyGooglism 159 | # Install googlism 160 | DetailPrint "Installing Googlism module..." 161 | SetDetailsPrint textonly 162 | SetOutPath $INSTDIR\scripts 163 | File scripts\googlism.py 164 | SetOutPath $INSTDIR\standard 165 | File standard\howie-googlism.aiml 166 | SetDetailsPrint both 167 | SectionEnd 168 | 169 | # Install rhyme 170 | Section "Rhymes" SecCopyRhyme 171 | DetailPrint "Installing Rhymes module..." 172 | SetDetailsPrint textonly 173 | SetOutPath $INSTDIR\scripts 174 | File scripts\rhyme.py 175 | File scripts\*.db 176 | SetOutPath $INSTDIR\standard 177 | File standard\howie-rhyme.aiml 178 | SetDetailsPrint both 179 | SectionEnd 180 | SubSectionEnd 181 | 182 | #-------------------------------- 183 | #Installer Functions 184 | 185 | Function .onInit 186 | # Splash screen 187 | #SetOutPath $TEMP 188 | #File /oname=spltmp.bmp "logo.bmp" 189 | #advsplash::show 2000 500 500 -1 $TEMP\spltmp 190 | 191 | # $0 has '1' if the user closed the splash screen early, 192 | # '0' if everything closed normal, and '-1' if some error occured. 193 | #Pop $0 194 | #Delete $TEMP\spltmp.bmp 195 | 196 | 197 | # Language selection 198 | 199 | # Font 200 | Push Tahoma 201 | Push 8 202 | 203 | # Languages 204 | !insertmacro MUI_LANGDLL_DISPLAY 205 | FunctionEnd 206 | 207 | #-------------------------------- 208 | #Descriptions 209 | 210 | !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN 211 | !insertmacro MUI_DESCRIPTION_TEXT ${SecCopyMain} $(DESC_SecCopyMain) 212 | !insertmacro MUI_DESCRIPTION_TEXT ${SecCopyAddOns} $(DESC_SecCopyAddOns) 213 | !insertmacro MUI_DESCRIPTION_TEXT ${SecCopyAcronym} $(DESC_SecCopyAcronym) 214 | !insertmacro MUI_DESCRIPTION_TEXT ${SecCopyGooglism} $(DESC_SecCopyGooglism) 215 | !insertmacro MUI_DESCRIPTION_TEXT ${SecCopyRhyme} $(DESC_SecCopyRhyme) 216 | !insertmacro MUI_FUNCTION_DESCRIPTION_END 217 | 218 | #-------------------------------- 219 | #Uninstaller Section 220 | 221 | Section "Uninstall" 222 | RMDir /r "$INSTDIR" 223 | !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP 224 | 225 | Delete "$SMPROGRAMS\$MUI_TEMP\Configure ${MY_PRODUCT}.lnk" 226 | Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall ${MY_PRODUCT}.lnk" 227 | Delete "$SMPROGRAMS\$MUI_TEMP\Run ${MY_PRODUCT}.lnk" 228 | Delete "$SMPROGRAMS\$MUI_TEMP\Run ${MY_PRODUCT} (Local Mode).lnk" 229 | Delete "$SMPROGRAMS\$MUI_TEMP\README.lnk" 230 | 231 | ;Delete empty start menu parent diretories 232 | StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" 233 | 234 | startMenuDeleteLoop: 235 | RMDir $MUI_TEMP 236 | GetFullPathName $MUI_TEMP "$MUI_TEMP\.." 237 | 238 | IfErrors startMenuDeleteLoopDone 239 | 240 | StrCmp $MUI_TEMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop 241 | startMenuDeleteLoopDone: 242 | 243 | DeleteRegKey /ifempty HKLM "Software\${MY_PRODUCT}" 244 | SectionEnd 245 | 246 | #-------------------------------- 247 | #Uninstaller Functions 248 | 249 | Function un.onInit 250 | # Get language from registry 251 | ReadRegStr $LANGUAGE HKLM "Software\${MY_PRODUCT}" "Installer Language" 252 | FunctionEnd 253 | -------------------------------------------------------------------------------- /howie/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ["configFile", "core"] 2 | -------------------------------------------------------------------------------- /howie/aiml/DefaultSubs.py: -------------------------------------------------------------------------------- 1 | """This file contains the default (English) substitutions for the 2 | PyAIML kernel. These substitutions may be overridden by using the 3 | Kernel.loadSubs(filename) method. The filename specified should refer 4 | to a Windows-style INI file with the following format: 5 | 6 | # lines that start with '#' are comments 7 | 8 | # The 'gender' section contains the substitutions performed by the 9 | # AIML tag, which swaps masculine and feminine pronouns. 10 | [gender] 11 | he = she 12 | she = he 13 | # and so on... 14 | 15 | # The 'person' section contains the substitutions performed by the 16 | # AIML tag, which swaps 1st and 2nd person pronouns. 17 | [person] 18 | I = you 19 | you = I 20 | # and so on... 21 | 22 | # The 'person2' section contains the substitutions performed by 23 | # the AIML tag, which swaps 1st and 3nd person pronouns. 24 | [person2] 25 | I = he 26 | he = I 27 | # and so on... 28 | 29 | # the 'normal' section contains subtitutions run on every input 30 | # string passed into Kernel.respond(). It's mainly used to 31 | # correct common misspellings, and to convert contractions 32 | # ("WHAT'S") into a format that will match an AIML pattern ("WHAT 33 | # IS"). 34 | [normal] 35 | what's = what is 36 | """ 37 | 38 | defaultGender = { 39 | # masculine -> feminine 40 | "he": "she", 41 | "him": "her", 42 | "his": "her", 43 | "himself": "herself", 44 | 45 | # feminine -> masculine 46 | "she": "he", 47 | "her": "him", 48 | "hers": "his", 49 | "herself": "himself", 50 | } 51 | 52 | defaultPerson = { 53 | # 1st->3rd (masculine) 54 | "I": "he", 55 | "me": "him", 56 | "my": "his", 57 | "mine": "his", 58 | "myself": "himself", 59 | 60 | # 3rd->1st (masculine) 61 | "he":"I", 62 | "him":"me", 63 | "his":"my", 64 | "himself":"myself", 65 | 66 | # 3rd->1st (feminine) 67 | "she":"I", 68 | "her":"me", 69 | "hers":"mine", 70 | "herself":"myself", 71 | } 72 | 73 | defaultPerson2 = { 74 | # 1st -> 2nd 75 | "I": "you", 76 | "me": "you", 77 | "my": "your", 78 | "mine": "yours", 79 | "myself": "yourself", 80 | 81 | # 2nd -> 1st 82 | "you": "me", 83 | "your": "my", 84 | "yours": "mine", 85 | "yourself": "myself", 86 | } 87 | 88 | 89 | # TODO: this list is far from complete 90 | defaultNormal = { 91 | "wanna": "want to", 92 | "gonna": "going to", 93 | 94 | "I'm": "I am", 95 | "I'd": "I would", 96 | "I'll": "I will", 97 | "I've": "I have", 98 | "you'd": "you would", 99 | "you're": "you are", 100 | "you've": "you have", 101 | "you'll": "you will", 102 | "he's": "he is", 103 | "he'd": "he would", 104 | "he'll": "he will", 105 | "she's": "she is", 106 | "she'd": "she would", 107 | "she'll": "she will", 108 | "we're": "we are", 109 | "we'd": "we would", 110 | "we'll": "we will", 111 | "we've": "we have", 112 | "they're": "they are", 113 | "they'd": "they would", 114 | "they'll": "they will", 115 | "they've": "they have", 116 | 117 | "y'all": "you all", 118 | 119 | "can't": "can not", 120 | "cannot": "can not", 121 | "couldn't": "could not", 122 | "wouldn't": "would not", 123 | "shouldn't": "should not", 124 | 125 | "isn't": "is not", 126 | "ain't": "is not", 127 | "don't": "do not", 128 | "aren't": "are not", 129 | "won't": "will not", 130 | "weren't": "were not", 131 | "wasn't": "was not", 132 | "didn't": "did not", 133 | "hasn't": "has not", 134 | "hadn't": "had not", 135 | "haven't": "have not", 136 | 137 | "where's": "where is", 138 | "where'd": "where did", 139 | "where'll": "where will", 140 | "who's": "who is", 141 | "who'd": "who did", 142 | "who'll": "who will", 143 | "what's": "what is", 144 | "what'd": "what did", 145 | "what'll": "what will", 146 | "when's": "when is", 147 | "when'd": "when did", 148 | "when'll": "when will", 149 | "why's": "why is", 150 | "why'd": "why did", 151 | "why'll": "why will", 152 | 153 | "it's": "it is", 154 | "it'd": "it would", 155 | "it'll": "it will", 156 | } -------------------------------------------------------------------------------- /howie/aiml/Kernel.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linzhp/Howie/c7aa0eb5ea55065870d10fdbc95baff243fac1dc/howie/aiml/Kernel.py -------------------------------------------------------------------------------- /howie/aiml/Utils.py: -------------------------------------------------------------------------------- 1 | """This file contains assorted general utility functions used by other 2 | modules in the PyAIML package. 3 | 4 | """ 5 | 6 | def sentences(s): 7 | """Split the string s into a list of sentences.""" 8 | try: s+"" 9 | except: raise TypeError, "s must be a string" 10 | pos = 0 11 | sentenceList = [] 12 | l = len(s) 13 | while pos < l: 14 | try: p = s.index('.', pos) 15 | except: p = l+1 16 | try: q = s.index('?', pos) 17 | except: q = l+1 18 | try: e = s.index('!', pos) 19 | except: e = l+1 20 | end = min(p,q,e) 21 | sentenceList.append( s[pos:end].strip() ) 22 | pos = end+1 23 | # If no sentences were found, return a one-item list containing 24 | # the entire input string. 25 | if len(sentenceList) == 0: sentenceList.append(s) 26 | return sentenceList 27 | 28 | # Self test 29 | if __name__ == "__main__": 30 | # sentences 31 | sents = sentences("First. Second, still? Third and Final! Well, not really") 32 | assert(len(sents) == 4) -------------------------------------------------------------------------------- /howie/aiml/WordSub.py: -------------------------------------------------------------------------------- 1 | """This module implements the WordSub class, modelled after a recipe 2 | in "Python Cookbook" (Recipe 3.14, "Replacing Multiple Patterns in a 3 | Single Pass" by Xavier Defrang). 4 | 5 | Usage: 6 | Use this class like a dictionary to add before/after pairs: 7 | > subber = TextSub() 8 | > subber["before"] = "after" 9 | > subber["begin"] = "end" 10 | Use the sub() method to perform the substitution: 11 | > print subber.sub("before we begin") 12 | after we end 13 | All matching is intelligently case-insensitive: 14 | > print subber.sub("Before we BEGIN") 15 | After we END 16 | The 'before' words must be complete words -- no prefixes. 17 | The following example illustrates this point: 18 | > subber["he"] = "she" 19 | > print subber.sub("he says he'd like to help her") 20 | she says she'd like to help her 21 | Note that "he" and "he'd" were replaced, but "help" and "her" were 22 | not. 23 | """ 24 | 25 | # 'dict' objects weren't available to subclass from until version 2.2. 26 | # Get around this by importing UserDict.UserDict if the built-in dict 27 | # object isn't available. 28 | try: dict 29 | except: from UserDict import UserDict as dict 30 | 31 | import ConfigParser 32 | import re 33 | import string 34 | 35 | class WordSub(dict): 36 | """All-in-one multiple-string-substitution class.""" 37 | 38 | def _wordToRegex(self, word): 39 | """Convert a word to a regex object which matches the word.""" 40 | return r"\b%s\b" % re.escape(word) 41 | 42 | def _update_regex(self): 43 | """Build re object based on the keys of the current 44 | dictionary. 45 | 46 | """ 47 | self._regex = re.compile("|".join(map(self._wordToRegex, self.keys()))) 48 | self._regexIsDirty = False 49 | 50 | def __init__(self, defaults = {}): 51 | """Initialize the object, and populate it with the entries in 52 | the defaults dictionary. 53 | 54 | """ 55 | self._regex = None 56 | self._regexIsDirty = True 57 | for k,v in defaults.items(): 58 | self[k] = v 59 | 60 | def __call__(self, match): 61 | """Handler invoked for each regex match.""" 62 | return self[match.group(0)] 63 | 64 | def __setitem__(self, i, y): 65 | self._regexIsDirty = True 66 | # for each entry the user adds, we actually add three entrys: 67 | super(type(self),self).__setitem__(string.lower(i),string.lower(y)) # key = value 68 | super(type(self),self).__setitem__(string.capwords(i), string.capwords(y)) # Key = Value 69 | super(type(self),self).__setitem__(string.upper(i), string.upper(y)) # KEY = VALUE 70 | 71 | def sub(self, text): 72 | """Translate text, returns the modified text.""" 73 | if self._regexIsDirty: 74 | self._update_regex() 75 | return self._regex.sub(self, text) 76 | 77 | # self-test 78 | if __name__ == "__main__": 79 | subber = WordSub() 80 | subber["apple"] = "banana" 81 | subber["orange"] = "pear" 82 | subber["banana" ] = "apple" 83 | subber["he"] = "she" 84 | subber["I'd"] = "I would" 85 | 86 | # test case insensitivity 87 | inStr = "I'd like one apple, one Orange and one BANANA." 88 | outStr = "I Would like one banana, one Pear and one APPLE." 89 | if subber.sub(inStr) == outStr: print "Test #1 PASSED" 90 | else: print "Test #1 FAILED: '%s'" % subber.sub(inStr) 91 | 92 | inStr = "He said he'd like to go with me" 93 | outStr = "She said she'd like to go with me" 94 | if subber.sub(inStr) == outStr: print "Test #2 PASSED" 95 | else: print "Test #2 FAILED: '%s'" % subber.sub(inStr) -------------------------------------------------------------------------------- /howie/aiml/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = [] 2 | 3 | # The Kernel class is the only class most implementations should need. 4 | from Kernel import Kernel 5 | -------------------------------------------------------------------------------- /howie/aiml/self-test.aiml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linzhp/Howie/c7aa0eb5ea55065870d10fdbc95baff243fac1dc/howie/aiml/self-test.aiml -------------------------------------------------------------------------------- /howie/configFile.py: -------------------------------------------------------------------------------- 1 | """ 2 | Handles the reading, writing of (and general access to) Howie's 3 | persistent configuration information, stored (by default) in 4 | the howie.ini file. 5 | """ 6 | 7 | import os 8 | import string 9 | import sys 10 | 11 | import ConfigParser 12 | from howie import frontends 13 | from frontends import * 14 | 15 | configFileName = "howie.ini" 16 | 17 | # Load default values for various config-file options. 18 | # The defaults are scattered throughout the frontend and 19 | # backend modules, each of which may have a dictionary 20 | # attribute called configDefaults similar to the one 21 | # below. This code merges all the configDefaults into 22 | # one master copy. 23 | configDefaults = { 24 | "general.logging": "no", 25 | "general.logdir": "logs", 26 | "general.maxdelay": "0", 27 | "general.sessionspersist": "no", 28 | "general.sessionsdir": "sessions", 29 | "general.verbose": "no", 30 | } 31 | for package in ['frontends']: 32 | for name in eval("%s.__all__" % package): 33 | mod = eval("%s.%s" % (package, name)) 34 | try: defaults = mod.configDefaults 35 | except AttributeError: continue 36 | for k,v in mod.configDefaults.items(): 37 | if configDefaults.has_key(k): 38 | continue 39 | configDefaults[k] = v 40 | 41 | 42 | def _WriteINI(file, config=configDefaults): 43 | """ 44 | Writes the config dictionary to a .INI file. 45 | """ 46 | if len(config) == 0: 47 | return 48 | iniFile = open(file, "w") 49 | currentSection = "" 50 | keys = config.keys() 51 | keys.sort() 52 | for key in keys: 53 | # Don't write entries with no value 54 | value = config[key] 55 | if value == "": 56 | continue 57 | 58 | # Split the key into section and variable. 59 | section, var = string.split(key, ".", 1) 60 | if section != currentSection: 61 | # start a new section 62 | if currentSection: 63 | iniFile.write("\n") 64 | iniFile.write("[%s]\n" % section) 65 | currentSection = section 66 | 67 | # write the entry 68 | iniFile.write("%s = %s\n" % (var, value)) 69 | iniFile.close() 70 | 71 | def _ReadINI(file, config={}): 72 | """ 73 | Returns a dictionary with keys of the form 74 |
.