py-dchub                          http://www.sourceforge.net/projects/py-dchub/
===============================================================================

Table of Contents
==================
1 Introduction
2 Special Features
3 License
4 Installation
5 Getting Started with py-dchub
6 Extending py-dchub
7 Unsupported Features
8 History

1 Introduction
===============

py-dchub is a cross platform Direct Connect Hub, written in Python.  It 
supports the entire Direct Connect Hub-Client protocol.  py-dchub is designed
to be easy to use, easy to extend, and easy to program bots for.

If you have any problems using py-dchub, please post a bug report on 
SourceForge.  Likewise, questions about py-dchub should be posted on the 
SourceForge messageboards.

2 Special Features
==================

py-dchub is similar to many other Direct Connect hubs, but there are some
features it has that few if any other hubs have:

1) Hub Reloading: Most hubs are programmed in compiled languages such as C or
	C++.  In order to make changes to the hub's internal programming, the hub
	needs to be shut down (and all users disconnected), recompiled, and started
	back up.  py-dchub, being programmed in Python, has the ability to reload 
	itself (this includes all related hub files, so reloading works with hub
	subclasses, assuming they are programmed appropriately), so you can make
	programming changes to the hub while it is running, call reload (or send a
	SIGHUP signal on systems that support it), and the hub will reload itself,
	giving you access to any features you added.  This process is transparent
	to the users of the hub. As far as I know, this is the only hub that has
	this feature, and it is unlikely that most hubs will ever be able to add
	it.
2) Full Access Bots: Most hubs have the ability to program bots for the hub.
	Typically, the bots are programmed in a different language than the hub
	itself, and they have a limited ability to change the hub itself.  
	py-dchub's bots have full access to the hub, they can change ANY aspect of
	the hub while it is running.
3) Portability: Most hubs run on a single operating system environment, or a
	couple of environments at most (there are a couple of Java hubs that are
	cross-platform).  py-dchub should run everywhere Python runs, assuming the
	platform supports sockets. Tested platforms include Windows, OpenBSD,
	Gentoo, and Debian.

3 License
=========

py-wired is released under the MIT License, which gives you freedom to do 
pretty much anything you want with it as long as you include a copy of the
license.  A copy of the license is included in the LICENSE file.

4 Installation
==============

Unzip/untar the the file, change to the created directory, edit the conf file
to reflect your settings, then run:

	python DCHub.py

If you are running a Unix based OS, you should create a system account named
dchub and run the above command as root (it'll chroot and drop privileges if
used with the default conf file).

Python 2.3 or greater is required.

5 Getting Started with py-dchub
===============================

py-dchub is fairly simple by default, there are just a few files you need to 
edit if you don't want to extend the hub:

conf - The main configuration file for the hub, in INI format.  You can set 
	most of the configurable options (including the locations of the files 
	mentioned below) here.  This file contains comments explaining what the
	options do.

accounts - List of accounts for the hub, in INI format.  If a user gives a nick
	that matches one of the account names, they are asked for a password 
	(unless the password for the account is blank).  If they don't give the 
	correct password, they are disconnected.  See the top of the file for 
	details on the format.

bans - Optional file that BanBot uses to keep track of banned IPs and nicks.

usercommands - List of user commands for the hub, in INI format.  See the top
	of the file for details on the format

welcome - The welcome message for the hub, given to users when they log in.

To add bots to the hub, place them in the bots directory.  There are some
example bots in the examples/bots directory:

AdvancedBot - A bot designed to work with AdvancedDCHub, serving as a front end
	to most of it's features, and handling other features internally.

BanBot - Allows ops to ban IPs or nicks for specific amounts to time.

LogBot - Allows ops to receive log messages generated by the hub.

OpChat - Allows for a private conversation between the ops, with the ability
	to message users anonymously, so all ops can follow the conversation.
	
OpChat-AdvancedDCHub - A version of OpChat designed to work with AdvancedDCHub.
	The regular version of OpChat still works, but this version doesn't require
	functions to be wrapped.
	
PythonBot - Bot allowing specific users to submit Python code to the hub and
	have the hub execute the hub in its own process.  Note that this is very 
	dangerous in the wrong hands, so only users with accounts and the string 
	PythonBot in the args for their account are allowed to submit commands.
	Note that in general you are going to want to use this bot, as making
	changes to the hub is fairly difficult otherwise.

There are also some example hubs in the examples/hubs folder. To use one of 
these hubs, move them to the directory with DCHub.py and execute them instead.

AdvancedDCHub - An advanced hub that builds on ThreadedDCHub and provides
	many additional features, such as automated account creation, user 
	verification, database storage, torrent getting/posting, punish users 
	(ban/silence/stupidify), getting the history of users (past login 
	times/lengths/IPs, punishments, verification, notes), automated password
	changes, reverse lookup on IP, and other useful features.  See the
	docstring in the file for more details.  

PrivateDCHub - This hub rejects anyone who doesn't have an account, useful
	for making sure only authorized members can access the hub.
	
ThreadedDCHub - This is a hub that uses threads to handle tasks that may block.
	By default, it doesn't use the extra threads, but bots and subclasses can
	use them.

6 Extending py-dchub
====================

There are two ways to extend py-dchub: bots and subclassing.  Bots allow for 
interaction with users via private messages, and have full access to the hub's
internals.  Subclassing allows for changes to the hubs structure or processes.
While either can be used to extend the hub in the same ways (i.e. the hub can 
interact with users directly via subclassing, and bots can modify the hub's 
structure and processes), it's best if bots do the interaction and subclassing 
does the structural changes.

See the bots and hubs in the examples directory to get a feel for how to
extend the hub.  To see the hub's functions you can use, run help(DCHub) in a
python shell.  Here are a few pointers to get you started:

Commands received from users go through 6 main stages.
1) badcommand - Checking for bad characters/reasonable command length
2) getcommandtype - Parsing the command to get the type of command (e.g. 
					MyINFO) and the argument string 
3) badprivileges - Checking that the user has the permission to send that
				   command type
4) parse* - (e.g. parseMyINFO) parse the argument string to break it discrete
			arguments (e.g. description, tag, email, etc.)
5) check* - (e.g. checkMyINFO) examine each argument to check for sanity (e.g.
			sharesize is an integer) and permissions (e.g. UserIP can only be
			used by non-ops to get their own IP)
6) got* - (e.g. gotMyINFO) executes the command (in this case, sets the user's 
		  MyINFO string and sends it to all users)
		  
If parse* or check* raise an exception, the exception is logged, and bad* is 
called.  parse* should return a tuple of arguments (which may be the empty 
tuple), if it returns None, further command processing is skipped. check* 
should return None if no changes need to be made to the arguments returned by
parse*, should return a new tuple of arguments if changes need to be made, and
should return False to skip further command processing.

When new socket connections are accepted, adduser is called.  When the user has
been successfully logged in, loginuser is called.  When the user leaves the hub
(or is otherwise disconnected), removeuser is called.

Bot authors that want to modify the hub's structure should create functions
that they want to execute before, after, or instead of the hub's current
functions.  They should add these functions to the correct dictionary 
(execbefore, execafter, or replace).  For example, to execute a function before
check_ChatMessage that checks for bad words, you would have code similar to:

	self.execbefore['check_ChatMessage'] = self.checkforbadwords
	
in the __init__ function of the bot.  

execbefore functions should take the same arguments as the function the are 
executing before.  They should generally return None unless you want to skip
further function processing (in which case you should return whatever you want
the function to return).  Note however that self in the hub functions refers to
the hub itself, while self in bot functions refers to the bot, so use self.hub
when refering to the hub instead bot functions.

execafter functions take one additional argument placed directly after self, 
called returnobj.  So if a hub function takes (self, user) as arguments, the
execafter function should take (self, returnobj, user) as arguments.  The
execafter function should return returnobj unless it wants to skip further
function processing (other execafter functions), in which case it should return
whatever you want the function to return.  The same warning about self applies
to execafter functions.

replace functions take the same arguments as the hub function.  2 bots cannot
replace the same function, if one tries, it is not added to the hub.  To call
the original hub function (e.g. check_ChatMessage) from a replace function, you
should call:

	hub.replacedfunctions['check_ChatMessage'](user, nick, message, *args)
	
Note that when bots are reloaded, all wrapped and replaced functions are
restored to their original state, and then the wrapping and replacing of
functions occurs as the bots are loaded.  For this reason, it's best to 
subclass when significantly changing the hub, so that reloading bots won't 
cause a lot of restoring and wrapping of functions.

7 Unsupported Features
======================

1) Hub linking
2) Ability to update the public hub list

These features are supported by a wide variety of other hubs.  py-dchub doesn't
currently have plans to support them, though they shouldn't be difficult to add
by extending the hub.  If you implement them through a subclass, please post
the python file on SourceForge so the feature can be added as an example hub.

8 History
==========
0.2.4 - 2006-02-13
- Allow any reasonable value for MyINFO speed
- Support pysqlite2 in AdvancedDCHub.py and CreateAdvancedDCHubDB.py
- Refactor AdvancedDCHub to only execute one SQL statement per query
0.2.3 - 2005-12-05
- Allow binding to more than one IP or port
- Don't shut down on error in listening socket
- Correctly set version when reloading
- Drop connections from users displaying 0 total slots in AdvancedDCHub
0.2.2 - 2005-08-05
- Allow use of upload speed as connection in MyINFO (used by DC++ >= v0.674)
- Move hub command for reloading bots from AdvancedDCHub to DCHub
- Only have one task runner by default in AdvancedDCHub
0.2.1 - 2005-06-18
- Fix bug where command line options are not processed if no conf file exists
- Fix bug where changing the uid or gid and chrooting was still attempted even
  if not run as root
- Fix bug where changing the ownership of the pidfile would still be attempted
  even if not run as root
- Catch likely errors regarding problems starting the server and display
  messages to users rather than tracebacks
- Allow chrooting even if not dropping privileges
- Change internal program defaults to debug=True, changeuidgid=False,
  pidfile='', and logfile=''; leave old defaults in conf file
- Under Windows, log to standard out even if debug != True
- Update README to explain about creating system accounts on Unix
- (AdvancedDCHub) Add ability for ops to get passwords for nonops
- (AdvancedDCHub) When kickbanning users, make sure they see the kickban
  message
0.2.0 - 2005-02-04
- Add hub reloading
- Add AdvancedDCHub, AdvancedBot, and OpChat-AdvancedDCHub, showing how easy
  py-dchub is to extend to add features
- More efficient handling in many places, use iterators in many places instead
  of building lists, check for bad characters with strings instead of lists,
  many lists are now sets, processing multiple outstanding commands at once,
  other performance enhancements
- Make logging much more configurable
- Auto login account holders with blank passwords
- Allow any character except the space in search terms
- Allow bots to be marked as inactive, so they don't get added to the hub
- Allow give_ChatMessage and give_PrivateMessage to use a string instead of a
  DCHubUser as the sender
- Allow TTH search datatype (and make it user configurable)
- Allow 28.8Kbps, 33.6Kbps, and ISDN as valid speeds
- Allow hostnames where previously only IPs were allowed
- Allow search response to omit file size, free slots, and total slots
- Add join flood protection
- Add logtimes function to log how long certain functions take
- Support /me and +me translation in private messages
- Make both clients and bots support the hub limits (though bots don't have to
  follow them if they don't want to)
- Make pingtime and timeperiod configurable on a per user basis
- More efficient task handling mechanism in ThreadedDCHub
- Better logging in ThreadedDCHub
- Ability to use threadlocal data easily in ThreadedDCHub
- Don't autostart many threads in ThreadedDCHub (though still use a thread
  pool)
- Make code more modular, to make extending easier
- Fix a bad MyINFO string kicking off users, instead of ignoring it for users
  who are already logged in
- Fix configuration files being reloaded keeping some old data
- Fix users not getting disconnected in certain cases
- Fix some users not getting the correct op list
- Fix giveUserCommand to give User Commands to all users
- Fix syslog logging
- Fix sys.path when chrooting
- Fix uncaught exception when checking passwords
- Fix occassional freezing of the hub when select doesn't work as it should
- Fix removeuser not removing bots from self.bots
- Fix cleanup code in ThreadedDCHub, try to make all threads exit
- Move license to separate file
0.1.0 - 2004-12-05
- Initial public release
