Browse Source

python-irclib from http://sourceforge.net/projects/python-irclib/

Jeff Balogh 15 years ago
commit
5c347d82f7
14 changed files with 3755 additions and 0 deletions
  1. 510 0
      COPYING
  2. 432 0
      ChangeLog
  3. 42 0
      Makefile
  4. 110 0
      README
  5. 77 0
      dccreceive
  6. 91 0
      dccsend
  7. 438 0
      ircbot.py
  8. 64 0
      irccat
  9. 66 0
      irccat2
  10. 1560 0
      irclib.py
  11. 74 0
      python-irclib.spec
  12. 164 0
      servermap
  13. 9 0
      setup.py
  14. 118 0
      testbot.py

+ 510 - 0
COPYING View File

@@ -0,0 +1,510 @@
1
+
2
+                  GNU LESSER GENERAL PUBLIC LICENSE
3
+                       Version 2.1, February 1999
4
+
5
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
6
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
7
+ Everyone is permitted to copy and distribute verbatim copies
8
+ of this license document, but changing it is not allowed.
9
+
10
+[This is the first released version of the Lesser GPL.  It also counts
11
+ as the successor of the GNU Library Public License, version 2, hence
12
+ the version number 2.1.]
13
+
14
+                            Preamble
15
+
16
+  The licenses for most software are designed to take away your
17
+freedom to share and change it.  By contrast, the GNU General Public
18
+Licenses are intended to guarantee your freedom to share and change
19
+free software--to make sure the software is free for all its users.
20
+
21
+  This license, the Lesser General Public License, applies to some
22
+specially designated software packages--typically libraries--of the
23
+Free Software Foundation and other authors who decide to use it.  You
24
+can use it too, but we suggest you first think carefully about whether
25
+this license or the ordinary General Public License is the better
26
+strategy to use in any particular case, based on the explanations
27
+below.
28
+
29
+  When we speak of free software, we are referring to freedom of use,
30
+not price.  Our General Public Licenses are designed to make sure that
31
+you have the freedom to distribute copies of free software (and charge
32
+for this service if you wish); that you receive source code or can get
33
+it if you want it; that you can change the software and use pieces of
34
+it in new free programs; and that you are informed that you can do
35
+these things.
36
+
37
+  To protect your rights, we need to make restrictions that forbid
38
+distributors to deny you these rights or to ask you to surrender these
39
+rights.  These restrictions translate to certain responsibilities for
40
+you if you distribute copies of the library or if you modify it.
41
+
42
+  For example, if you distribute copies of the library, whether gratis
43
+or for a fee, you must give the recipients all the rights that we gave
44
+you.  You must make sure that they, too, receive or can get the source
45
+code.  If you link other code with the library, you must provide
46
+complete object files to the recipients, so that they can relink them
47
+with the library after making changes to the library and recompiling
48
+it.  And you must show them these terms so they know their rights.
49
+
50
+  We protect your rights with a two-step method: (1) we copyright the
51
+library, and (2) we offer you this license, which gives you legal
52
+permission to copy, distribute and/or modify the library.
53
+
54
+  To protect each distributor, we want to make it very clear that
55
+there is no warranty for the free library.  Also, if the library is
56
+modified by someone else and passed on, the recipients should know
57
+that what they have is not the original version, so that the original
58
+author's reputation will not be affected by problems that might be
59
+introduced by others.
60
+^L
61
+  Finally, software patents pose a constant threat to the existence of
62
+any free program.  We wish to make sure that a company cannot
63
+effectively restrict the users of a free program by obtaining a
64
+restrictive license from a patent holder.  Therefore, we insist that
65
+any patent license obtained for a version of the library must be
66
+consistent with the full freedom of use specified in this license.
67
+
68
+  Most GNU software, including some libraries, is covered by the
69
+ordinary GNU General Public License.  This license, the GNU Lesser
70
+General Public License, applies to certain designated libraries, and
71
+is quite different from the ordinary General Public License.  We use
72
+this license for certain libraries in order to permit linking those
73
+libraries into non-free programs.
74
+
75
+  When a program is linked with a library, whether statically or using
76
+a shared library, the combination of the two is legally speaking a
77
+combined work, a derivative of the original library.  The ordinary
78
+General Public License therefore permits such linking only if the
79
+entire combination fits its criteria of freedom.  The Lesser General
80
+Public License permits more lax criteria for linking other code with
81
+the library.
82
+
83
+  We call this license the "Lesser" General Public License because it
84
+does Less to protect the user's freedom than the ordinary General
85
+Public License.  It also provides other free software developers Less
86
+of an advantage over competing non-free programs.  These disadvantages
87
+are the reason we use the ordinary General Public License for many
88
+libraries.  However, the Lesser license provides advantages in certain
89
+special circumstances.
90
+
91
+  For example, on rare occasions, there may be a special need to
92
+encourage the widest possible use of a certain library, so that it
93
+becomes a de-facto standard.  To achieve this, non-free programs must
94
+be allowed to use the library.  A more frequent case is that a free
95
+library does the same job as widely used non-free libraries.  In this
96
+case, there is little to gain by limiting the free library to free
97
+software only, so we use the Lesser General Public License.
98
+
99
+  In other cases, permission to use a particular library in non-free
100
+programs enables a greater number of people to use a large body of
101
+free software.  For example, permission to use the GNU C Library in
102
+non-free programs enables many more people to use the whole GNU
103
+operating system, as well as its variant, the GNU/Linux operating
104
+system.
105
+
106
+  Although the Lesser General Public License is Less protective of the
107
+users' freedom, it does ensure that the user of a program that is
108
+linked with the Library has the freedom and the wherewithal to run
109
+that program using a modified version of the Library.
110
+
111
+  The precise terms and conditions for copying, distribution and
112
+modification follow.  Pay close attention to the difference between a
113
+"work based on the library" and a "work that uses the library".  The
114
+former contains code derived from the library, whereas the latter must
115
+be combined with the library in order to run.
116
+^L
117
+                  GNU LESSER GENERAL PUBLIC LICENSE
118
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
119
+
120
+  0. This License Agreement applies to any software library or other
121
+program which contains a notice placed by the copyright holder or
122
+other authorized party saying it may be distributed under the terms of
123
+this Lesser General Public License (also called "this License").
124
+Each licensee is addressed as "you".
125
+
126
+  A "library" means a collection of software functions and/or data
127
+prepared so as to be conveniently linked with application programs
128
+(which use some of those functions and data) to form executables.
129
+
130
+  The "Library", below, refers to any such software library or work
131
+which has been distributed under these terms.  A "work based on the
132
+Library" means either the Library or any derivative work under
133
+copyright law: that is to say, a work containing the Library or a
134
+portion of it, either verbatim or with modifications and/or translated
135
+straightforwardly into another language.  (Hereinafter, translation is
136
+included without limitation in the term "modification".)
137
+
138
+  "Source code" for a work means the preferred form of the work for
139
+making modifications to it.  For a library, complete source code means
140
+all the source code for all modules it contains, plus any associated
141
+interface definition files, plus the scripts used to control
142
+compilation and installation of the library.
143
+
144
+  Activities other than copying, distribution and modification are not
145
+covered by this License; they are outside its scope.  The act of
146
+running a program using the Library is not restricted, and output from
147
+such a program is covered only if its contents constitute a work based
148
+on the Library (independent of the use of the Library in a tool for
149
+writing it).  Whether that is true depends on what the Library does
150
+and what the program that uses the Library does.
151
+
152
+  1. You may copy and distribute verbatim copies of the Library's
153
+complete source code as you receive it, in any medium, provided that
154
+you conspicuously and appropriately publish on each copy an
155
+appropriate copyright notice and disclaimer of warranty; keep intact
156
+all the notices that refer to this License and to the absence of any
157
+warranty; and distribute a copy of this License along with the
158
+Library.
159
+
160
+  You may charge a fee for the physical act of transferring a copy,
161
+and you may at your option offer warranty protection in exchange for a
162
+fee.
163
+
164
+  2. You may modify your copy or copies of the Library or any portion
165
+of it, thus forming a work based on the Library, and copy and
166
+distribute such modifications or work under the terms of Section 1
167
+above, provided that you also meet all of these conditions:
168
+
169
+    a) The modified work must itself be a software library.
170
+
171
+    b) You must cause the files modified to carry prominent notices
172
+    stating that you changed the files and the date of any change.
173
+
174
+    c) You must cause the whole of the work to be licensed at no
175
+    charge to all third parties under the terms of this License.
176
+
177
+    d) If a facility in the modified Library refers to a function or a
178
+    table of data to be supplied by an application program that uses
179
+    the facility, other than as an argument passed when the facility
180
+    is invoked, then you must make a good faith effort to ensure that,
181
+    in the event an application does not supply such function or
182
+    table, the facility still operates, and performs whatever part of
183
+    its purpose remains meaningful.
184
+
185
+    (For example, a function in a library to compute square roots has
186
+    a purpose that is entirely well-defined independent of the
187
+    application.  Therefore, Subsection 2d requires that any
188
+    application-supplied function or table used by this function must
189
+    be optional: if the application does not supply it, the square
190
+    root function must still compute square roots.)
191
+
192
+These requirements apply to the modified work as a whole.  If
193
+identifiable sections of that work are not derived from the Library,
194
+and can be reasonably considered independent and separate works in
195
+themselves, then this License, and its terms, do not apply to those
196
+sections when you distribute them as separate works.  But when you
197
+distribute the same sections as part of a whole which is a work based
198
+on the Library, the distribution of the whole must be on the terms of
199
+this License, whose permissions for other licensees extend to the
200
+entire whole, and thus to each and every part regardless of who wrote
201
+it.
202
+
203
+Thus, it is not the intent of this section to claim rights or contest
204
+your rights to work written entirely by you; rather, the intent is to
205
+exercise the right to control the distribution of derivative or
206
+collective works based on the Library.
207
+
208
+In addition, mere aggregation of another work not based on the Library
209
+with the Library (or with a work based on the Library) on a volume of
210
+a storage or distribution medium does not bring the other work under
211
+the scope of this License.
212
+
213
+  3. You may opt to apply the terms of the ordinary GNU General Public
214
+License instead of this License to a given copy of the Library.  To do
215
+this, you must alter all the notices that refer to this License, so
216
+that they refer to the ordinary GNU General Public License, version 2,
217
+instead of to this License.  (If a newer version than version 2 of the
218
+ordinary GNU General Public License has appeared, then you can specify
219
+that version instead if you wish.)  Do not make any other change in
220
+these notices.
221
+^L
222
+  Once this change is made in a given copy, it is irreversible for
223
+that copy, so the ordinary GNU General Public License applies to all
224
+subsequent copies and derivative works made from that copy.
225
+
226
+  This option is useful when you wish to copy part of the code of
227
+the Library into a program that is not a library.
228
+
229
+  4. You may copy and distribute the Library (or a portion or
230
+derivative of it, under Section 2) in object code or executable form
231
+under the terms of Sections 1 and 2 above provided that you accompany
232
+it with the complete corresponding machine-readable source code, which
233
+must be distributed under the terms of Sections 1 and 2 above on a
234
+medium customarily used for software interchange.
235
+
236
+  If distribution of object code is made by offering access to copy
237
+from a designated place, then offering equivalent access to copy the
238
+source code from the same place satisfies the requirement to
239
+distribute the source code, even though third parties are not
240
+compelled to copy the source along with the object code.
241
+
242
+  5. A program that contains no derivative of any portion of the
243
+Library, but is designed to work with the Library by being compiled or
244
+linked with it, is called a "work that uses the Library".  Such a
245
+work, in isolation, is not a derivative work of the Library, and
246
+therefore falls outside the scope of this License.
247
+
248
+  However, linking a "work that uses the Library" with the Library
249
+creates an executable that is a derivative of the Library (because it
250
+contains portions of the Library), rather than a "work that uses the
251
+library".  The executable is therefore covered by this License.
252
+Section 6 states terms for distribution of such executables.
253
+
254
+  When a "work that uses the Library" uses material from a header file
255
+that is part of the Library, the object code for the work may be a
256
+derivative work of the Library even though the source code is not.
257
+Whether this is true is especially significant if the work can be
258
+linked without the Library, or if the work is itself a library.  The
259
+threshold for this to be true is not precisely defined by law.
260
+
261
+  If such an object file uses only numerical parameters, data
262
+structure layouts and accessors, and small macros and small inline
263
+functions (ten lines or less in length), then the use of the object
264
+file is unrestricted, regardless of whether it is legally a derivative
265
+work.  (Executables containing this object code plus portions of the
266
+Library will still fall under Section 6.)
267
+
268
+  Otherwise, if the work is a derivative of the Library, you may
269
+distribute the object code for the work under the terms of Section 6.
270
+Any executables containing that work also fall under Section 6,
271
+whether or not they are linked directly with the Library itself.
272
+^L
273
+  6. As an exception to the Sections above, you may also combine or
274
+link a "work that uses the Library" with the Library to produce a
275
+work containing portions of the Library, and distribute that work
276
+under terms of your choice, provided that the terms permit
277
+modification of the work for the customer's own use and reverse
278
+engineering for debugging such modifications.
279
+
280
+  You must give prominent notice with each copy of the work that the
281
+Library is used in it and that the Library and its use are covered by
282
+this License.  You must supply a copy of this License.  If the work
283
+during execution displays copyright notices, you must include the
284
+copyright notice for the Library among them, as well as a reference
285
+directing the user to the copy of this License.  Also, you must do one
286
+of these things:
287
+
288
+    a) Accompany the work with the complete corresponding
289
+    machine-readable source code for the Library including whatever
290
+    changes were used in the work (which must be distributed under
291
+    Sections 1 and 2 above); and, if the work is an executable linked
292
+    with the Library, with the complete machine-readable "work that
293
+    uses the Library", as object code and/or source code, so that the
294
+    user can modify the Library and then relink to produce a modified
295
+    executable containing the modified Library.  (It is understood
296
+    that the user who changes the contents of definitions files in the
297
+    Library will not necessarily be able to recompile the application
298
+    to use the modified definitions.)
299
+
300
+    b) Use a suitable shared library mechanism for linking with the
301
+    Library.  A suitable mechanism is one that (1) uses at run time a
302
+    copy of the library already present on the user's computer system,
303
+    rather than copying library functions into the executable, and (2)
304
+    will operate properly with a modified version of the library, if
305
+    the user installs one, as long as the modified version is
306
+    interface-compatible with the version that the work was made with.
307
+
308
+    c) Accompany the work with a written offer, valid for at least
309
+    three years, to give the same user the materials specified in
310
+    Subsection 6a, above, for a charge no more than the cost of
311
+    performing this distribution.
312
+
313
+    d) If distribution of the work is made by offering access to copy
314
+    from a designated place, offer equivalent access to copy the above
315
+    specified materials from the same place.
316
+
317
+    e) Verify that the user has already received a copy of these
318
+    materials or that you have already sent this user a copy.
319
+
320
+  For an executable, the required form of the "work that uses the
321
+Library" must include any data and utility programs needed for
322
+reproducing the executable from it.  However, as a special exception,
323
+the materials to be distributed need not include anything that is
324
+normally distributed (in either source or binary form) with the major
325
+components (compiler, kernel, and so on) of the operating system on
326
+which the executable runs, unless that component itself accompanies
327
+the executable.
328
+
329
+  It may happen that this requirement contradicts the license
330
+restrictions of other proprietary libraries that do not normally
331
+accompany the operating system.  Such a contradiction means you cannot
332
+use both them and the Library together in an executable that you
333
+distribute.
334
+^L
335
+  7. You may place library facilities that are a work based on the
336
+Library side-by-side in a single library together with other library
337
+facilities not covered by this License, and distribute such a combined
338
+library, provided that the separate distribution of the work based on
339
+the Library and of the other library facilities is otherwise
340
+permitted, and provided that you do these two things:
341
+
342
+    a) Accompany the combined library with a copy of the same work
343
+    based on the Library, uncombined with any other library
344
+    facilities.  This must be distributed under the terms of the
345
+    Sections above.
346
+
347
+    b) Give prominent notice with the combined library of the fact
348
+    that part of it is a work based on the Library, and explaining
349
+    where to find the accompanying uncombined form of the same work.
350
+
351
+  8. You may not copy, modify, sublicense, link with, or distribute
352
+the Library except as expressly provided under this License.  Any
353
+attempt otherwise to copy, modify, sublicense, link with, or
354
+distribute the Library is void, and will automatically terminate your
355
+rights under this License.  However, parties who have received copies,
356
+or rights, from you under this License will not have their licenses
357
+terminated so long as such parties remain in full compliance.
358
+
359
+  9. You are not required to accept this License, since you have not
360
+signed it.  However, nothing else grants you permission to modify or
361
+distribute the Library or its derivative works.  These actions are
362
+prohibited by law if you do not accept this License.  Therefore, by
363
+modifying or distributing the Library (or any work based on the
364
+Library), you indicate your acceptance of this License to do so, and
365
+all its terms and conditions for copying, distributing or modifying
366
+the Library or works based on it.
367
+
368
+  10. Each time you redistribute the Library (or any work based on the
369
+Library), the recipient automatically receives a license from the
370
+original licensor to copy, distribute, link with or modify the Library
371
+subject to these terms and conditions.  You may not impose any further
372
+restrictions on the recipients' exercise of the rights granted herein.
373
+You are not responsible for enforcing compliance by third parties with
374
+this License.
375
+^L
376
+  11. If, as a consequence of a court judgment or allegation of patent
377
+infringement or for any other reason (not limited to patent issues),
378
+conditions are imposed on you (whether by court order, agreement or
379
+otherwise) that contradict the conditions of this License, they do not
380
+excuse you from the conditions of this License.  If you cannot
381
+distribute so as to satisfy simultaneously your obligations under this
382
+License and any other pertinent obligations, then as a consequence you
383
+may not distribute the Library at all.  For example, if a patent
384
+license would not permit royalty-free redistribution of the Library by
385
+all those who receive copies directly or indirectly through you, then
386
+the only way you could satisfy both it and this License would be to
387
+refrain entirely from distribution of the Library.
388
+
389
+If any portion of this section is held invalid or unenforceable under
390
+any particular circumstance, the balance of the section is intended to
391
+apply, and the section as a whole is intended to apply in other
392
+circumstances.
393
+
394
+It is not the purpose of this section to induce you to infringe any
395
+patents or other property right claims or to contest validity of any
396
+such claims; this section has the sole purpose of protecting the
397
+integrity of the free software distribution system which is
398
+implemented by public license practices.  Many people have made
399
+generous contributions to the wide range of software distributed
400
+through that system in reliance on consistent application of that
401
+system; it is up to the author/donor to decide if he or she is willing
402
+to distribute software through any other system and a licensee cannot
403
+impose that choice.
404
+
405
+This section is intended to make thoroughly clear what is believed to
406
+be a consequence of the rest of this License.
407
+
408
+  12. If the distribution and/or use of the Library is restricted in
409
+certain countries either by patents or by copyrighted interfaces, the
410
+original copyright holder who places the Library under this License
411
+may add an explicit geographical distribution limitation excluding those
412
+countries, so that distribution is permitted only in or among
413
+countries not thus excluded.  In such case, this License incorporates
414
+the limitation as if written in the body of this License.
415
+
416
+  13. The Free Software Foundation may publish revised and/or new
417
+versions of the Lesser General Public License from time to time.
418
+Such new versions will be similar in spirit to the present version,
419
+but may differ in detail to address new problems or concerns.
420
+
421
+Each version is given a distinguishing version number.  If the Library
422
+specifies a version number of this License which applies to it and
423
+"any later version", you have the option of following the terms and
424
+conditions either of that version or of any later version published by
425
+the Free Software Foundation.  If the Library does not specify a
426
+license version number, you may choose any version ever published by
427
+the Free Software Foundation.
428
+^L
429
+  14. If you wish to incorporate parts of the Library into other free
430
+programs whose distribution conditions are incompatible with these,
431
+write to the author to ask for permission.  For software which is
432
+copyrighted by the Free Software Foundation, write to the Free
433
+Software Foundation; we sometimes make exceptions for this.  Our
434
+decision will be guided by the two goals of preserving the free status
435
+of all derivatives of our free software and of promoting the sharing
436
+and reuse of software generally.
437
+
438
+                            NO WARRANTY
439
+
440
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
441
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
442
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
443
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
444
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
445
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
446
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
447
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
448
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
449
+
450
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
451
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
452
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
453
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
454
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
455
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
456
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
457
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
458
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
459
+DAMAGES.
460
+
461
+                     END OF TERMS AND CONDITIONS
462
+^L
463
+           How to Apply These Terms to Your New Libraries
464
+
465
+  If you develop a new library, and you want it to be of the greatest
466
+possible use to the public, we recommend making it free software that
467
+everyone can redistribute and change.  You can do so by permitting
468
+redistribution under these terms (or, alternatively, under the terms
469
+of the ordinary General Public License).
470
+
471
+  To apply these terms, attach the following notices to the library.
472
+It is safest to attach them to the start of each source file to most
473
+effectively convey the exclusion of warranty; and each file should
474
+have at least the "copyright" line and a pointer to where the full
475
+notice is found.
476
+
477
+
478
+    <one line to give the library's name and a brief idea of what it does.>
479
+    Copyright (C) <year>  <name of author>
480
+
481
+    This library is free software; you can redistribute it and/or
482
+    modify it under the terms of the GNU Lesser General Public
483
+    License as published by the Free Software Foundation; either
484
+    version 2.1 of the License, or (at your option) any later version.
485
+
486
+    This library is distributed in the hope that it will be useful,
487
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
488
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
489
+    Lesser General Public License for more details.
490
+
491
+    You should have received a copy of the GNU Lesser General Public
492
+    License along with this library; if not, write to the Free Software
493
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
494
+
495
+Also add information on how to contact you by electronic and paper mail.
496
+
497
+You should also get your employer (if you work as a programmer) or
498
+your school, if any, to sign a "copyright disclaimer" for the library,
499
+if necessary.  Here is a sample; alter the names:
500
+
501
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
502
+  library `Frob' (a library for tweaking knobs) written by James
503
+  Random Hacker.
504
+
505
+  <signature of Ty Coon>, 1 April 1990
506
+  Ty Coon, President of Vice
507
+
508
+That's all there is to it!
509
+
510
+

+ 432 - 0
ChangeLog View File

@@ -0,0 +1,432 @@
1
+2008-09-11  Keltus <keltus@users.sourceforge.net>
2
+    * ircbot.py: Reverted a leftover testing fragment that broke ircbot.py
3
+
4
+2008-08-29  Keltus <keltus@users.sourceforge.net>
5
+    * irclib.py: Reverted changes in irclib that don't really belong in the core lib
6
+    * irclib.py: Add support for ssl
7
+    * irclib.py: Add support for ipv6
8
+	* python-irclib now requires python 2.3 and above (for ssl and ipv6)
9
+
10
+2006-03-09  Keltus <keltus@users.sourceforge.net>
11
+	* README: Minor update
12
+
13
+2005-12-24  Keltus <keltus@users.sourceforge.net>
14
+	* Released version 0.4.6.
15
+
16
+	* irclib.py (VERSION):
17
+	* python-irclib.spec.in:
18
+	Preparations for version 0.4.6.
19
+
20
+2005-12-23  Keltus <keltus@users.sourceforge.net>
21
+	* dccsend:
22
+	* dccreceive:
23
+	* irclib.py:
24
+	* ircbot.py:
25
+	* irccat:
26
+	* irccat2:
27
+	* servermap:
28
+	* testbot.py:
29
+	Code modernization - String methods used instead of deprecated
30
+	string functions, keyword 'in' used for membership testing instead
31
+	of 'has_key' method, etc.
32
+
33
+2005-12-06  Keltus <keltus@users.sourceforge.net>
34
+	* irclib.py (ServerConnection.process_data): Reversed fix from
35
+	2005-05-28. This is strange because there was a bug before and
36
+	now it's gone. Either python changed something, or the IRC
37
+	networks changed something. Confirmed by peter.
38
+
39
+2005-11-03  Keltus <keltus@users.sourceforge.net>
40
+	* irclib.py (numeric_events): Renamed numeric code 332 from topic
41
+	to currenttopic (the message when "/topic <chan>" is sent), so it
42
+	doesn't collide with TOPIC (the message when the topic is set).
43
+
44
+2005-08-27  Keltus <keltus@users.sourceforge.net>
45
+	* irclib.py (ServerConnection.disconnect): Fixed infinitely
46
+	recursive calls when disconnecting with a failed connection. Bug
47
+	reported by Erik Max Francis.
48
+
49
+2005-08-18  Keltus <keltus@users.sourceforge.net>
50
+	* irclib.py: Made ServerConnection.disconnect more consistant and
51
+	changed some functions to use it instead of quit. Previously,
52
+	disconnect would ignore the quit message, but now it sends a quit
53
+	message and disconnect. Suggestion by Erik Max Francis.
54
+	* ircbot.py: Changed to use ServerConnection.disconnect instead of
55
+	ServerConnection.quit as well.
56
+
57
+2005-05-28  Keltus <keltus@users.sourceforge.net>
58
+	* irclib.py (ServerConnection.process_data): Fixed quit arguments
59
+	to return a list rather than a list of a list. Patch from peter.
60
+
61
+2005-05-18  Keltus <keltus@users.sourceforge.net>
62
+	* Released version 0.4.5.
63
+
64
+	* irclib.py (ServerConnection.__init__): Added self.socket = None
65
+	to be able to process events when ServerConnection is not
66
+	connected to a socket. Patch from alst.
67
+
68
+	* irclib.py (VERSION):
69
+	* python-irclib.spec.in:
70
+	Preparations for version 0.4.5.
71
+
72
+2005-04-26  Keltus <keltus@users.sourceforge.net>
73
+	* irclib.py (IRC.__doc__): Corrected server.process_forever() to
74
+	irc.process_forever(). Suggestion by olecom.
75
+
76
+2005-04-17  Keltus <keltus@users.sourceforge.net>
77
+	* irclib.py (ServerConnection.process_data): Moved event
78
+	translation code.
79
+	* irclib.py (ServerConnection): Reverted the 2005-01-28 change
80
+	because it breaks jump_server().
81
+	* irclib.py: minor comment changes
82
+
83
+2005-04-03  Keltus <keltus@users.sourceforge.net>
84
+	* irclib.py (protocol_events): Added "pong" and "invite" events.
85
+	Patch from Adam Mikuta.
86
+	* irclib.py (ServerConnection.part): Added message parameter.
87
+	Patch from Adam Mikuta.
88
+
89
+2005-02-23  Keltus <keltus@users.sourceforge.net>
90
+	* Released version 0.4.4.
91
+
92
+	* irclib.py (VERSION):
93
+	* python-irclib.spec.in:
94
+	Preparations for version 0.4.4.
95
+
96
+2005-01-28  Keltus <keltus@users.sourceforge.net>
97
+	* irclib.py: (ServerConnection): Moved
98
+	self.irclibobj._remove_connection call from	close() to
99
+	disconnect(). Patch from Alexey Nezhdanov.
100
+
101
+2005-01-25  Keltus <keltus@users.sourceforge.net>
102
+	* irclib.py (ServerConnection.connect): closes socket if a
103
+	connection does not occur
104
+	* irclib.py (ServerConnection.connect): "Changing server" ->
105
+	"Changing servers" (more ubiquitous quit phrase)
106
+
107
+2005-01-23  Keltus <keltus@users.sourceforge.net>
108
+
109
+	* irclib.py: Removed depreciated apply functions. python-irclib is
110
+	now compatible with Python 1.6 and above.
111
+	* testbot.py: Removed redundant extra start() call
112
+
113
+2005-01-20  Joel Rosdahl  <joel@rosdahl.net>
114
+
115
+	* Released version 0.4.3.
116
+	* Makefile: Removed more GNU make specific constructs.
117
+
118
+2005-01-19  Joel Rosdahl  <joel@rosdahl.net>
119
+
120
+	* Makefile: Don't require GNU make.
121
+
122
+2005-01-19  Keltus  <keltus@users.sourceforge.net>
123
+
124
+	* ircbot.py (IRCDict.__iter__): Added __iter__ method for IRCDict.
125
+
126
+2005-01-17  Joel Rosdahl  <joel@rosdahl.net>
127
+
128
+	* ircbot.py (IRCDict.__contains__): Added __contains__method for
129
+	IRCDict. Patch from Keltus.
130
+	(SingleServerIRCBot.on_ctcp): Corrected default decoding of CTCP
131
+	DCC CHAT. Patch from Keltus.
132
+
133
+	* irclib.py (VERSION):
134
+	* python-irclib.spec.in:
135
+	Preparations for version 0.4.3.
136
+
137
+	* debian: Removed Debian package directory since python-irclib is
138
+	in Debian now.
139
+
140
+	* ircbot.py (SingleServerIRCBot._on_namreply): Improved comment
141
+	about arguments to the function. Patch from Keltus.
142
+	(Channel.has_allow_external_messages): Renamed from
143
+	has_message_from_outside_protection. Patch from Keltus.
144
+
145
+	* irclib.py (ServerConnection.quit): Added comment about how some
146
+	IRC servers' treat QUIT messages. Patch from Keltus.
147
+
148
+	* ircbot.py (SingleServerIRCBot.jump_server): Improved jump_server
149
+	behaviour. Patch from Keltus.
150
+
151
+2004-08-04  Joel Rosdahl  <joel@rosdahl.net>
152
+
153
+	* irclib.py (ServerConnection.process_data): Added "bonus" action
154
+	event that is triggered on CTCP ACTION messages.
155
+
156
+2004-07-09  Joel Rosdahl  <joel@rosdahl.net>
157
+
158
+	* Released version 0.4.2.
159
+
160
+	* debian/rules: Remove built *.pyc files before making package.
161
+
162
+	* irclib.py (DEBUG):
163
+	* debian/changelog:
164
+	* python-irclib.spec.in:
165
+	Preparations for version 0.4.2.
166
+
167
+	* irclib.py (ServerNotConnectedError): New exception.
168
+	(ServerConnection.send_raw): Fix bug #922446, "Raise
169
+	IllegalStateException in send_raw when disconnected".
170
+
171
+2003-10-30  Joel Rosdahl  <joel@rosdahl.net>
172
+
173
+	* Released version 0.4.1.
174
+
175
+	* debian/examples: Added dccreceive and dccsend as example files
176
+	in Debian.
177
+
178
+	* python-irclib.spec.in: Likewise.
179
+
180
+2003-10-29  Joel Rosdahl  <joel@rosdahl.net>
181
+
182
+	* debian: Added Debian packaging files.
183
+
184
+	* setup.py.in: Create setup.py from setup.py.in.
185
+
186
+	* python-irclib.spec.in: RPM spec file from Gary Benson.
187
+
188
+	* testbot.py (TestBot.on_nicknameinuse): New method.
189
+
190
+	* irclib.py (ServerConnection.process_data): Record nickname when
191
+	welcome message is sent to trap nickname change triggered in a
192
+	nicknameinuse callback.
193
+
194
+	* ircbot.py (SingleServerIRCBot._on_join): Use
195
+	Connection.get_nickname instead of relying on self._nickname.
196
+	(SingleServerIRCBot._on_kick): Likewise.
197
+	(SingleServerIRCBot._on_part): And here too.
198
+	(SingleServerIRCBot._on_nick): No need to remember nickname change
199
+	here.
200
+
201
+2003-08-31  Joel Rosdahl  <joel@rosdahl.net>
202
+
203
+	* Released version 0.4.0.
204
+
205
+	Implemented DCC support (based on patches from Adam Langley and
206
+	Marco Bettio):
207
+
208
+	* irclib.py (IRC.dcc): New method.
209
+	(DCCConnectionError): New class.
210
+	(DCCConnection): New class.
211
+	(SimpleIRCClient.__init__): Added dcc_connections attribute.
212
+	(SimpleIRCClient._dcc_disconnect): New method.
213
+	(SimpleIRCClient.connect): Added localaddress and
214
+	localport parameters. The socket will be bound accordingly before
215
+	connecting.
216
+	(SimpleIRCClient.dcc_connect): New method.
217
+	(SimpleIRCClient.dcc_listen): New method.
218
+	(ip_numstr_to_quad): New function.
219
+	(ip_quad_to_numstr): New function.
220
+
221
+	* ircbot.py (SingleServerIRCBot.on_ctcp): Relay DCC CHAT CTCPs to
222
+	the on_dccchat method.
223
+
224
+	* testbot.py: Added support for accepting DCC chats and for
225
+	initiating DCC chats via a "dcc" command.
226
+
227
+	* dccreceive: New example program.
228
+
229
+	* dccsend: New example program.
230
+
231
+	* Makefile: Added dccreceive and dccsend to dist files.
232
+
233
+	Other changes:
234
+
235
+	* setup.py: Added.
236
+
237
+	* irclib.py (ServerConnection.connect, ServerConnection.user):
238
+	Send USER command according to RFC 2812.
239
+	(ServerConnection.connect): Added localaddress and
240
+	localport parameters. The socket will be bound accordingly before
241
+	connecting.
242
+	(ServerConnection.process_data): Ignore empty lines from the
243
+	server. (Patch by Jason Wies.)
244
+	(ServerConnection._get_socket): Simplified.
245
+	(ServerConnection.remove_global_handler): Added. (Patch from
246
+	Brandon Beck.)
247
+
248
+	* ircbot.py (SingleServerIRCBot.on_ctcp): Prepend VERSION reply
249
+	with VERSION. (Patch from Andrew Gaul.)
250
+
251
+	* Makefile: Added setup.py to dist files. Also create zip archive.
252
+
253
+	* README: Added requirements and installation sections.
254
+
255
+2002-03-01  Joel Rosdahl  <joel@rosdahl.net>
256
+
257
+	* Released version 0.3.4.
258
+
259
+	Corrected problems spotted by Markku Hänninen <hmm@iki.fi>:
260
+
261
+	* irccat2 (IRCCat.on_welcome): Added missing connection argument.
262
+	(IRCCat.on_join): Likewise.
263
+	(IRCCat.on_disconnect): Likewise.
264
+
265
+	* irclib.py (ServerConnection.ison): Bug fix: Join nicks by space
266
+	instead of commas.
267
+
268
+	* irclib.py (ServerConnection.whowas): Bug fix: Let the max
269
+	argument default to the empty string.
270
+
271
+	* irclib.py (numeric_events): Added new events: traceservice,
272
+	tracereconnect, tryagain, invitelist, endofinvitelist, exceptlist,
273
+	endofexceptlist, unavailresource, nochanmodes, banlistfull,
274
+	restricted and uniqopprivsneeded.
275
+
276
+2002-02-17  Joel Rosdahl  <joel@rosdahl.net>
277
+
278
+	* Released version 0.3.3.
279
+
280
+	* Makefile, README, .cvsignore: Removed documentation generated by
281
+	pythondoc.  Use pydoc instead.
282
+
283
+	* servermap: Removed some excess whitespace.
284
+
285
+	* README: Mention http://python-irclib.sourceforge.net.
286
+
287
+	* Makefile (dist): Changed archive name from irclib-* to
288
+	python-irclib-*.
289
+
290
+	Changed license from GPL 2 to LGPL 2.1:
291
+
292
+	* COPYING: New license text.
293
+
294
+	* irclib.py, ircbot.py, servermap: New license header.
295
+
296
+2001-10-21  Joel Rosdahl  <joel@rosdahl.net>
297
+
298
+	* Released version 0.3.2.
299
+
300
+	* irclib.py (_parse_modes): Fixed problem found by Tom Morton: the
301
+	mode parsing code bailed out if a unary mode character didn't have
302
+	a corresponding argument.
303
+
304
+	* irclib.py (_alpha): Fixed bug found by Tom Morton: w was missing
305
+	in the alphabet used by irc_lower().
306
+
307
+	* ircbot.py: Removed redundant import of is_channel.
308
+
309
+	* servermap: Clarified copyright and license.
310
+
311
+	* irccat: Ditto.
312
+
313
+	* irccat2: Ditto.
314
+
315
+2000-12-11  Joel Rosdahl  <joel@rosdahl.net>
316
+
317
+	* Released version 0.3.1.
318
+
319
+	* irclib.py (IRC.process_once): Work-around for platform-dependent
320
+	select() on Windows systems.
321
+
322
+	* ircbot.py: Clarification of SingleServerIRCBot doc string.
323
+
324
+2000-11-26  Joel Rosdahl  <joel@rosdahl.net>
325
+
326
+	* Released version 0.3.0.
327
+
328
+	* Makefile (dist): Include ircbot.py again.
329
+
330
+	* README: Updated.
331
+
332
+	* irclib.py (ServerConnection.get_nickname): Renamed from
333
+	get_nick_name.
334
+	(ServerConnection._get_socket): Return None if not connected.
335
+
336
+2000-11-25  Joel Rosdahl  <joel@rosdahl.net>
337
+
338
+	* irclib.py (ServerConnection.process_data): all_raw_messages
339
+	instead of allrawmessages.
340
+	(IRC._handle_event): Added "all_events" event type.
341
+	(nm_to_n): Renamed from nick_from_nickmask.
342
+	(nm_to_uh): Renamed from userhost_from_nickmask.
343
+	(nm_to_h): Renamed from host_from_nickmask.
344
+	(nm_to_u): Renamed from user_from_nickmask.
345
+	(SimpleIRCClient): Created.
346
+
347
+2000-11-22  Joel Rosdahl  <joel@rosdahl.net>
348
+
349
+	* irclib.py (lower_irc_string): Use translation instead.
350
+	(ServerConnection.process_data): Split non-RFC-compliant lines a
351
+	bit more intelligently.
352
+	(ServerConnection.process_data): Removed unnecessary try/except
353
+	block.
354
+	(ServerConnection.get_server_name): Return empty server if
355
+	unknown.
356
+	(_rfc_1459_command_regexp): Tweaked a bit.
357
+
358
+	* ircbot.py: Rewritten.
359
+
360
+2000-11-21  Joel Rosdahl  <joel@rosdahl.net>
361
+
362
+	* irclib.py (IRC.process_forever): Default to processing a bit
363
+	more often.
364
+
365
+2000-10-29  Joel Rosdahl  <joel@rosdahl.net>
366
+
367
+	* Released version 0.2.4.
368
+
369
+	* Makefile (dist): Include generated documentation in
370
+	distribution.
371
+
372
+	* Makefile (doc): Make documentation.
373
+
374
+	* irclib.py: Updated documentation.
375
+
376
+	* irclib.py (is_channel): Included "!" as channel prefix.
377
+
378
+2000-10-02  Joel Rosdahl  <joel@rosdahl.net>
379
+
380
+	* Released version 0.2.3.
381
+
382
+	* irclib.py (ServerConnection.connect): Make socket.connect() work
383
+	for Python >= 1.6.
384
+
385
+2000-09-26  Joel Rosdahl  <joel@rosdahl.net>
386
+
387
+	* Released version 0.2.2.
388
+
389
+	* irclib.py (ServerConnection.user): Fixed erroneous format
390
+	string.
391
+
392
+2000-09-24  Joel Rosdahl  <joel@rosdahl.net>
393
+
394
+	* Released version 0.2.1.
395
+
396
+	* irclib.py (ServerConnection.process_data): Bug fix (didn't keep
397
+	track of nick name).
398
+	(IRC.process_once): New method.
399
+	(ServerConnection.process_data): Bug fix.
400
+	(IRC.disconnect_all): Created.
401
+	(IRC.exit): Removed.
402
+	(ServerConnection.exit): Removed.
403
+	(ServerConnection.connect): Follow RFC closer.
404
+	(ServerConnection.user): Follow RFC closer.
405
+
406
+	* ircbot.py: Removed.
407
+
408
+	* irccat (on_disconnect): Just sys.exit(0).
409
+
410
+	* servermap (on_disconnect): Just sys.exit(0).
411
+
412
+	* irclib.py: Various documentation and some clean-ups.
413
+
414
+1999-08-21  Joel Rosdahl  <joel@rosdahl.net>
415
+
416
+	* Released version 0.2.0.
417
+
418
+	* servermap: Updated to work with irclib 0.2.0.
419
+
420
+	* irccat: Updated to work with irclib 0.2.0.
421
+
422
+	* ircbot.py: Updated to work with irclib 0.2.0.  The bot now
423
+ 	checks every minute that it is connected.  If it's not, it
424
+ 	reconnects.
425
+
426
+	* irclib.py: Changes in how to create a ServerConnection object.
427
+  	Made the code for handling disconnection hopefully more robust.
428
+  	Renamed connect() to sconnect().
429
+
430
+1999-06-19  Joel Rosdahl  <joel@rosdahl.net>
431
+
432
+	* irclib.py: Released 0.1.0.

+ 42 - 0
Makefile View File

@@ -0,0 +1,42 @@
1
+VERSION := `sed -n -e '/VERSION = /{s/VERSION = \(.*\), \(.*\), \(.*\)/\1.\2.\3/;p;}' <irclib.py`
2
+
3
+DISTFILES = \
4
+    COPYING \
5
+    ChangeLog \
6
+    Makefile \
7
+    README \
8
+    dccreceive \
9
+    dccsend \
10
+    ircbot.py \
11
+    irccat \
12
+    irccat2 \
13
+    irclib.py \
14
+    python-irclib.spec \
15
+    servermap \
16
+    setup.py \
17
+    testbot.py
18
+
19
+PACKAGENAME = python-irclib-$(VERSION)
20
+
21
+all: $(DISTFILES)
22
+
23
+setup.py: setup.py.in
24
+	sed 's/%%VERSION%%/'$(VERSION)'/g' setup.py.in >setup.py
25
+
26
+python-irclib.spec: python-irclib.spec.in
27
+	sed 's/%%VERSION%%/'$(VERSION)'/g' python-irclib.spec.in >python-irclib.spec
28
+
29
+dist: $(DISTFILES)
30
+	mkdir $(PACKAGENAME)
31
+	cp -r $(DISTFILES) $(PACKAGENAME)
32
+	tar cvzf $(PACKAGENAME).tar.gz $(PACKAGENAME)
33
+	zip -r9yq $(PACKAGENAME).zip $(PACKAGENAME)
34
+	rm -rf $(PACKAGENAME)
35
+
36
+cvstag:
37
+	ver=$(VERSION); echo cvs tag version_`echo $$ver | sed 's/\./_/g'`
38
+
39
+clean:
40
+	rm -rf *~ *.pyc build python-irclib.spec setup.py
41
+
42
+.PHONY: all doc dist cvstag clean

+ 110 - 0
README View File

@@ -0,0 +1,110 @@
1
+irclib -- Internet Relay Chat (IRC) protocol client library
2
+-----------------------------------------------------------
3
+
4
+The home of irclib.py is now:
5
+
6
+    http://python-irclib.sourceforge.net
7
+
8
+This library is intended to encapsulate the IRC protocol at a quite
9
+low level.  It provides an event-driven IRC client framework.  It has
10
+a fairly thorough support for the basic IRC protocol, CTCP and DCC
11
+connections.
12
+
13
+In order to understand how to make an IRC client, I'm afraid you more
14
+or less must understand the IRC specifications.  They are available
15
+here:
16
+
17
+    http://www.irchelp.org/irchelp/rfc/
18
+
19
+Requirements:
20
+
21
+  * Python 2.2 or newer.
22
+
23
+Installation:
24
+
25
+  * Run "python setup.py install" or copy irclib.py and/or ircbot.py
26
+    to an appropriate Python module directory.
27
+
28
+The main features of the IRC client framework are:
29
+
30
+  * Abstraction of the IRC protocol.
31
+  * Handles multiple simultaneous IRC server connections.
32
+  * Handles server PONGing transparently.
33
+  * Messages to the IRC server are done by calling methods on an IRC
34
+    connection object.
35
+  * Messages from an IRC server triggers events, which can be caught
36
+    by event handlers.
37
+  * Reading from and writing to IRC server sockets are normally done
38
+    by an internal select() loop, but the select()ing may be done by
39
+    an external main loop.
40
+  * Functions can be registered to execute at specified times by the
41
+    event-loop.
42
+  * Decodes CTCP tagging correctly (hopefully); I haven't seen any
43
+    other IRC client implementation that handles the CTCP
44
+    specification subtilties.
45
+  * A kind of simple, single-server, object-oriented IRC client class
46
+    that dispatches events to instance methods is included.
47
+  * DCC connection support.
48
+
49
+Current limitations:
50
+
51
+  * The IRC protocol shines through the abstraction a bit too much.
52
+  * Data is not written asynchronously to the server (and DCC peers),
53
+    i.e. the write() may block if the TCP buffers are stuffed.
54
+  * Like most projects, documentation is lacking...
55
+
56
+Unfortunately, this library isn't as well-documented as I would like
57
+it to be.  I think the best way to get started is to read and
58
+understand the example program irccat, which is included in the
59
+distribution.
60
+
61
+The following files might be of interest:
62
+
63
+  * irclib.py
64
+
65
+    The library itself.  Read the code along with comments and
66
+    docstrings to get a grip of what it does.  Use it at your own risk
67
+    and read the source, Luke!
68
+
69
+  * irccat
70
+
71
+    A simple example of how to use irclib.py.  irccat reads text from
72
+    stdin and writes it to a specified user or channel on an IRC
73
+    server.
74
+
75
+  * irccat2
76
+
77
+    The same as above, but using the SimpleIRCClient class.
78
+
79
+  * servermap
80
+
81
+    Another simple example.  servermap connects to an IRC server,
82
+    finds out what other IRC servers there are in the net and prints
83
+    a tree-like map of their interconnections.
84
+
85
+  * testbot.py
86
+
87
+    An example bot that uses the SingleServerIRCBot class from
88
+    ircbot.py.  The bot enters a channel and listens for commands in
89
+    private messages or channel traffic.  It also accepts DCC
90
+    invitations and echos back sent DCC chat messages.
91
+
92
+  * dccreceive
93
+
94
+    Receives a file over DCC.
95
+
96
+  * dccsend
97
+
98
+    Sends a file over DCC.
99
+
100
+
101
+NOTE: If you're running one of the examples on a unix command line, you need to escape the # symbol in the channel. For example, use \#test instead of #test.
102
+
103
+
104
+Enjoy.
105
+
106
+Maintainer:
107
+keltus <keltus@users.sourceforge.net>
108
+
109
+Original Author:
110
+Joel Rosdahl <joel@rosdahl.net>

+ 77 - 0
dccreceive View File

@@ -0,0 +1,77 @@
1
+#! /usr/bin/env python
2
+#
3
+# Example program using irclib.py.
4
+#
5
+# This program is free without restrictions; do anything you like with
6
+# it.
7
+#
8
+# Joel Rosdahl <joel@rosdahl.net>
9
+
10
+import irclib
11
+import os
12
+import struct
13
+import sys
14
+
15
+class DCCReceive(irclib.SimpleIRCClient):
16
+    def __init__(self):
17
+        irclib.SimpleIRCClient.__init__(self)
18
+        self.received_bytes = 0
19
+
20
+    def on_ctcp(self, connection, event):
21
+        args = event.arguments()[1].split()
22
+        if args[0] != "SEND":
23
+            return
24
+        self.filename = os.path.basename(args[1])
25
+        if os.path.exists(self.filename):
26
+            print "A file named", self.filename,
27
+            print "already exists. Refusing to save it."
28
+            self.connection.quit()
29
+        self.file = open(self.filename, "w")
30
+        peeraddress = irclib.ip_numstr_to_quad(args[2])
31
+        peerport = int(args[3])
32
+        self.dcc = self.dcc_connect(peeraddress, peerport, "raw")
33
+
34
+    def on_dccmsg(self, connection, event):
35
+        data = event.arguments()[0]
36
+        self.file.write(data)
37
+        self.received_bytes = self.received_bytes + len(data)
38
+        self.dcc.privmsg(struct.pack("!I", self.received_bytes))
39
+
40
+    def on_dcc_disconnect(self, connection, event):
41
+        self.file.close()
42
+        print "Received file %s (%d bytes)." % (self.filename,
43
+                                                self.received_bytes)
44
+        self.connection.quit()
45
+
46
+    def on_disconnect(self, connection, event):
47
+        sys.exit(0)
48
+
49
+def main():
50
+    if len(sys.argv) != 3:
51
+        print "Usage: dccreceive <server[:port]> <nickname>"
52
+        print "\nReceives one file via DCC and then exits.  The file is stored in the"
53
+        print "current directory."
54
+        sys.exit(1)
55
+
56
+    s = sys.argv[1].split(":", 1)
57
+    server = s[0]
58
+    if len(s) == 2:
59
+        try:
60
+            port = int(s[1])
61
+        except ValueError:
62
+            print "Error: Erroneous port."
63
+            sys.exit(1)
64
+    else:
65
+        port = 6667
66
+    nickname = sys.argv[2]
67
+
68
+    c = DCCReceive()
69
+    try:
70
+        c.connect(server, port, nickname)
71
+    except irclib.ServerConnectionError, x:
72
+        print x
73
+        sys.exit(1)
74
+    c.start()
75
+
76
+if __name__ == "__main__":
77
+    main()

+ 91 - 0
dccsend View File

@@ -0,0 +1,91 @@
1
+#! /usr/bin/env python
2
+#
3
+# Example program using irclib.py.
4
+#
5
+# This program is free without restrictions; do anything you like with
6
+# it.
7
+#
8
+# Joel Rosdahl <joel@rosdahl.net>
9
+
10
+import irclib
11
+import os
12
+import struct
13
+import sys
14
+
15
+class DCCSend(irclib.SimpleIRCClient):
16
+    def __init__(self, receiver, filename):
17
+        irclib.SimpleIRCClient.__init__(self)
18
+        self.receiver = receiver
19
+        self.filename = filename
20
+        self.filesize = os.path.getsize(self.filename)
21
+        self.file = open(filename)
22
+        self.sent_bytes = 0
23
+
24
+    def on_welcome(self, connection, event):
25
+        self.dcc = self.dcc_listen("raw")
26
+        self.connection.ctcp("DCC", self.receiver, "SEND %s %s %d %d" % (
27
+            os.path.basename(self.filename),
28
+            irclib.ip_quad_to_numstr(self.dcc.localaddress),
29
+            self.dcc.localport,
30
+            self.filesize))
31
+
32
+    def on_dcc_connect(self, connection, event):
33
+        if self.filesize == 0:
34
+            self.dcc.disconnect()
35
+            return
36
+        self.send_chunk()
37
+
38
+    def on_dcc_disconnect(self, connection, event):
39
+        print "Sent file %s (%d bytes)." % (self.filename, self.filesize)
40
+        self.connection.quit()
41
+
42
+    def on_dccmsg(self, connection, event):
43
+        acked = struct.unpack("!I", event.arguments()[0])[0]
44
+        if acked == self.filesize:
45
+            self.dcc.disconnect()
46
+            self.connection.quit()
47
+        elif acked == self.sent_bytes:
48
+            self.send_chunk()
49
+
50
+    def on_disconnect(self, connection, event):
51
+        sys.exit(0)
52
+
53
+    def on_nosuchnick(self, connection, event):
54
+        print "No such nickname:", event.arguments()[0]
55
+        self.connection.quit()
56
+
57
+    def send_chunk(self):
58
+        data = self.file.read(1024)
59
+        self.dcc.privmsg(data)
60
+        self.sent_bytes = self.sent_bytes + len(data)
61
+
62
+def main():
63
+    if len(sys.argv) != 5:
64
+        print "Usage: dccsend <server[:port]> <nickname> <receiver nickname> <filename>"
65
+        print "\nSends <filename> to <receiver nickname> via DCC and then exits."
66
+        sys.exit(1)
67
+
68
+    s = sys.argv[1].split(":", 1)
69
+    server = s[0]
70
+    if len(s) == 2:
71
+        try:
72
+            port = int(s[1])
73
+        except ValueError:
74
+            print "Error: Erroneous port."
75
+            sys.exit(1)
76
+    else:
77
+        port = 6667
78
+    nickname = sys.argv[2]
79
+    receiver = sys.argv[3]
80
+    filename = sys.argv[4]
81
+
82
+    c = DCCSend(receiver, filename)
83
+    try:
84
+        c.connect(server, port, nickname)
85
+    except irclib.ServerConnectionError, x:
86
+        print x
87
+        sys.exit(1)
88
+    c.start()
89
+
90
+if __name__ == "__main__":
91
+    main()

+ 438 - 0
ircbot.py View File

@@ -0,0 +1,438 @@
1
+# Copyright (C) 1999--2002  Joel Rosdahl
2
+#
3
+# This library is free software; you can redistribute it and/or
4
+# modify it under the terms of the GNU Lesser General Public
5
+# License as published by the Free Software Foundation; either
6
+# version 2.1 of the License, or (at your option) any later version.
7
+#
8
+# This library is distributed in the hope that it will be useful,
9
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+# Lesser General Public License for more details.
12
+#
13
+# You should have received a copy of the GNU Lesser General Public
14
+# License along with this library; if not, write to the Free Software
15
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
16
+#
17
+# Joel Rosdahl <joel@rosdahl.net>
18
+#
19
+# $Id: ircbot.py,v 1.23 2008/09/11 07:38:30 keltus Exp $
20
+
21
+"""ircbot -- Simple IRC bot library.
22
+
23
+This module contains a single-server IRC bot class that can be used to
24
+write simpler bots.
25
+"""
26
+
27
+import sys
28
+from UserDict import UserDict
29
+
30
+from irclib import SimpleIRCClient
31
+from irclib import nm_to_n, irc_lower, all_events
32
+from irclib import parse_channel_modes, is_channel
33
+from irclib import ServerConnectionError
34
+
35
+class SingleServerIRCBot(SimpleIRCClient):
36
+    """A single-server IRC bot class.
37
+
38
+    The bot tries to reconnect if it is disconnected.
39
+
40
+    The bot keeps track of the channels it has joined, the other
41
+    clients that are present in the channels and which of those that
42
+    have operator or voice modes.  The "database" is kept in the
43
+    self.channels attribute, which is an IRCDict of Channels.
44
+    """
45
+    def __init__(self, server_list, nickname, realname, reconnection_interval=60):
46
+        """Constructor for SingleServerIRCBot objects.
47
+
48
+        Arguments:
49
+
50
+            server_list -- A list of tuples (server, port) that
51
+                           defines which servers the bot should try to
52
+                           connect to.
53
+
54
+            nickname -- The bot's nickname.
55
+
56
+            realname -- The bot's realname.
57
+
58
+            reconnection_interval -- How long the bot should wait
59
+                                     before trying to reconnect.
60
+
61
+            dcc_connections -- A list of initiated/accepted DCC
62
+            connections.
63
+        """
64
+
65
+        SimpleIRCClient.__init__(self)
66
+        self.channels = IRCDict()
67
+        self.server_list = server_list
68
+        if not reconnection_interval or reconnection_interval < 0:
69
+            reconnection_interval = 2**31
70
+        self.reconnection_interval = reconnection_interval
71
+
72
+        self._nickname = nickname
73
+        self._realname = realname
74
+        for i in ["disconnect", "join", "kick", "mode",
75
+                  "namreply", "nick", "part", "quit"]:
76
+            self.connection.add_global_handler(i,
77
+                                               getattr(self, "_on_" + i),
78
+                                               -10)
79
+    def _connected_checker(self):
80
+        """[Internal]"""
81
+        if not self.connection.is_connected():
82
+            self.connection.execute_delayed(self.reconnection_interval,
83
+                                            self._connected_checker)
84
+            self.jump_server()
85
+
86
+    def _connect(self):
87
+        """[Internal]"""
88
+        password = None
89
+        if len(self.server_list[0]) > 2:
90
+            password = self.server_list[0][2]
91
+        try:
92
+            self.connect(self.server_list[0][0],
93
+                         self.server_list[0][1],
94
+                         self._nickname,
95
+                         password,
96
+                         ircname=self._realname)
97
+        except ServerConnectionError:
98
+            pass
99
+
100
+    def _on_disconnect(self, c, e):
101
+        """[Internal]"""
102
+        self.channels = IRCDict()
103
+        self.connection.execute_delayed(self.reconnection_interval,
104
+                                        self._connected_checker)
105
+
106
+    def _on_join(self, c, e):
107
+        """[Internal]"""
108
+        ch = e.target()
109
+        nick = nm_to_n(e.source())
110
+        if nick == c.get_nickname():
111
+            self.channels[ch] = Channel()
112
+        self.channels[ch].add_user(nick)
113
+
114
+    def _on_kick(self, c, e):
115
+        """[Internal]"""
116
+        nick = e.arguments()[0]
117
+        channel = e.target()
118
+
119
+        if nick == c.get_nickname():
120
+            del self.channels[channel]
121
+        else:
122
+            self.channels[channel].remove_user(nick)
123
+
124
+    def _on_mode(self, c, e):
125
+        """[Internal]"""
126
+        modes = parse_channel_modes(" ".join(e.arguments()))
127
+        t = e.target()
128
+        if is_channel(t):
129
+            ch = self.channels[t]
130
+            for mode in modes:
131
+                if mode[0] == "+":
132
+                    f = ch.set_mode
133
+                else:
134
+                    f = ch.clear_mode
135
+                f(mode[1], mode[2])
136
+        else:
137
+            # Mode on self... XXX
138
+            pass
139
+
140
+    def _on_namreply(self, c, e):
141
+        """[Internal]"""
142
+
143
+        # e.arguments()[0] == "@" for secret channels,
144
+        #                     "*" for private channels,
145
+        #                     "=" for others (public channels)
146
+        # e.arguments()[1] == channel
147
+        # e.arguments()[2] == nick list
148
+
149
+        ch = e.arguments()[1]
150
+        for nick in e.arguments()[2].split():
151
+            if nick[0] == "@":
152
+                nick = nick[1:]
153
+                self.channels[ch].set_mode("o", nick)
154
+            elif nick[0] == "+":
155
+                nick = nick[1:]
156
+                self.channels[ch].set_mode("v", nick)
157
+            self.channels[ch].add_user(nick)
158
+
159
+    def _on_nick(self, c, e):
160
+        """[Internal]"""
161
+        before = nm_to_n(e.source())
162
+        after = e.target()
163
+        for ch in self.channels.values():
164
+            if ch.has_user(before):
165
+                ch.change_nick(before, after)
166
+
167
+    def _on_part(self, c, e):
168
+        """[Internal]"""
169
+        nick = nm_to_n(e.source())
170
+        channel = e.target()
171
+
172
+        if nick == c.get_nickname():
173
+            del self.channels[channel]
174
+        else:
175
+            self.channels[channel].remove_user(nick)
176
+
177
+    def _on_quit(self, c, e):
178
+        """[Internal]"""
179
+        nick = nm_to_n(e.source())
180
+        for ch in self.channels.values():
181
+            if ch.has_user(nick):
182
+                ch.remove_user(nick)
183
+
184
+    def die(self, msg="Bye, cruel world!"):
185
+        """Let the bot die.
186
+
187
+        Arguments:
188
+
189
+            msg -- Quit message.
190
+        """
191
+
192
+        self.connection.disconnect(msg)
193
+        sys.exit(0)
194
+
195
+    def disconnect(self, msg="I'll be back!"):
196
+        """Disconnect the bot.
197
+
198
+        The bot will try to reconnect after a while.
199
+
200
+        Arguments:
201
+
202
+            msg -- Quit message.
203
+        """
204
+        self.connection.disconnect(msg)
205
+
206
+    def get_version(self):
207
+        """Returns the bot version.
208
+
209
+        Used when answering a CTCP VERSION request.
210
+        """
211
+        return "ircbot.py by Joel Rosdahl <joel@rosdahl.net>"
212
+
213
+    def jump_server(self, msg="Changing servers"):
214
+        """Connect to a new server, possibly disconnecting from the current.
215
+
216
+        The bot will skip to next server in the server_list each time
217
+        jump_server is called.
218
+        """
219
+        if self.connection.is_connected():
220
+            self.connection.disconnect(msg)
221
+
222
+        self.server_list.append(self.server_list.pop(0))
223
+        self._connect()
224
+
225
+    def on_ctcp(self, c, e):
226
+        """Default handler for ctcp events.
227
+
228
+        Replies to VERSION and PING requests and relays DCC requests
229
+        to the on_dccchat method.
230
+        """
231
+        if e.arguments()[0] == "VERSION":
232
+            c.ctcp_reply(nm_to_n(e.source()),
233
+                         "VERSION " + self.get_version())
234
+        elif e.arguments()[0] == "PING":
235
+            if len(e.arguments()) > 1:
236
+                c.ctcp_reply(nm_to_n(e.source()),
237
+                             "PING " + e.arguments()[1])
238
+        elif e.arguments()[0] == "DCC" and e.arguments()[1].split(" ", 1)[0] == "CHAT":
239
+            self.on_dccchat(c, e)
240
+
241
+    def on_dccchat(self, c, e):
242
+        pass
243
+
244
+    def start(self):
245
+        """Start the bot."""
246
+        self._connect()
247
+        SimpleIRCClient.start(self)
248
+
249
+
250
+class IRCDict:
251
+    """A dictionary suitable for storing IRC-related things.
252
+
253
+    Dictionary keys a and b are considered equal if and only if
254
+    irc_lower(a) == irc_lower(b)
255
+
256
+    Otherwise, it should behave exactly as a normal dictionary.
257
+    """
258
+
259
+    def __init__(self, dict=None):
260
+        self.data = {}
261
+        self.canon_keys = {}  # Canonical keys
262
+        if dict is not None:
263
+            self.update(dict)
264
+    def __repr__(self):
265
+        return repr(self.data)
266
+    def __cmp__(self, dict):
267
+        if isinstance(dict, IRCDict):
268
+            return cmp(self.data, dict.data)
269
+        else:
270
+            return cmp(self.data, dict)
271
+    def __len__(self):
272
+        return len(self.data)
273
+    def __getitem__(self, key):
274
+        return self.data[self.canon_keys[irc_lower(key)]]
275
+    def __setitem__(self, key, item):
276
+        if key in self:
277
+            del self[key]
278
+        self.data[key] = item
279
+        self.canon_keys[irc_lower(key)] = key
280
+    def __delitem__(self, key):
281
+        ck = irc_lower(key)
282
+        del self.data[self.canon_keys[ck]]
283
+        del self.canon_keys[ck]
284
+    def __iter__(self):
285
+        return iter(self.data)
286
+    def __contains__(self, key):
287
+        return self.has_key(key)
288
+    def clear(self):
289
+        self.data.clear()
290
+        self.canon_keys.clear()
291
+    def copy(self):
292
+        if self.__class__ is UserDict:
293
+            return UserDict(self.data)
294
+        import copy
295
+        return copy.copy(self)
296
+    def keys(self):
297
+        return self.data.keys()
298
+    def items(self):
299
+        return self.data.items()
300
+    def values(self):
301
+        return self.data.values()
302
+    def has_key(self, key):
303
+        return irc_lower(key) in self.canon_keys
304
+    def update(self, dict):
305
+        for k, v in dict.items():
306
+            self.data[k] = v
307
+    def get(self, key, failobj=None):
308
+        return self.data.get(key, failobj)
309
+
310
+
311
+class Channel:
312
+    """A class for keeping information about an IRC channel.
313
+
314
+    This class can be improved a lot.
315
+    """
316
+
317
+    def __init__(self):
318
+        self.userdict = IRCDict()
319
+        self.operdict = IRCDict()
320
+        self.voiceddict = IRCDict()
321
+        self.modes = {}
322
+
323
+    def users(self):
324
+        """Returns an unsorted list of the channel's users."""
325
+        return self.userdict.keys()
326
+
327
+    def opers(self):
328
+        """Returns an unsorted list of the channel's operators."""
329
+        return self.operdict.keys()
330
+
331
+    def voiced(self):
332
+        """Returns an unsorted list of the persons that have voice
333
+        mode set in the channel."""
334
+        return self.voiceddict.keys()
335
+
336
+    def has_user(self, nick):
337
+        """Check whether the channel has a user."""
338
+        return nick in self.userdict
339
+
340
+    def is_oper(self, nick):
341
+        """Check whether a user has operator status in the channel."""
342
+        return nick in self.operdict
343
+
344
+    def is_voiced(self, nick):
345
+        """Check whether a user has voice mode set in the channel."""
346
+        return nick in self.voiceddict
347
+
348
+    def add_user(self, nick):
349
+        self.userdict[nick] = 1
350
+
351
+    def remove_user(self, nick):
352
+        for d in self.userdict, self.operdict, self.voiceddict:
353
+            if nick in d:
354
+                del d[nick]
355
+
356
+    def change_nick(self, before, after):
357
+        self.userdict[after] = 1
358
+        del self.userdict[before]
359
+        if before in self.operdict:
360
+            self.operdict[after] = 1
361
+            del self.operdict[before]
362
+        if before in self.voiceddict:
363
+            self.voiceddict[after] = 1
364
+            del self.voiceddict[before]
365
+
366
+    def set_mode(self, mode, value=None):
367
+        """Set mode on the channel.
368
+
369
+        Arguments:
370
+
371
+            mode -- The mode (a single-character string).
372
+
373
+            value -- Value
374
+        """
375
+        if mode == "o":
376
+            self.operdict[value] = 1
377
+        elif mode == "v":
378
+            self.voiceddict[value] = 1
379
+        else:
380
+            self.modes[mode] = value
381
+
382
+    def clear_mode(self, mode, value=None):
383
+        """Clear mode on the channel.
384
+
385
+        Arguments:
386
+
387
+            mode -- The mode (a single-character string).
388
+
389
+            value -- Value
390
+        """
391
+        try:
392
+            if mode == "o":
393
+                del self.operdict[value]
394
+            elif mode == "v":
395
+                del self.voiceddict[value]
396
+            else:
397
+                del self.modes[mode]
398
+        except KeyError:
399
+            pass
400
+
401
+    def has_mode(self, mode):
402
+        return mode in self.modes
403
+
404
+    def is_moderated(self):
405
+        return self.has_mode("m")
406
+
407
+    def is_secret(self):
408
+        return self.has_mode("s")
409
+
410
+    def is_protected(self):
411
+        return self.has_mode("p")
412
+
413
+    def has_topic_lock(self):
414
+        return self.has_mode("t")
415
+
416
+    def is_invite_only(self):
417
+        return self.has_mode("i")
418
+
419
+    def has_allow_external_messages(self):
420
+        return self.has_mode("n")
421
+
422
+    def has_limit(self):
423
+        return self.has_mode("l")
424
+
425
+    def limit(self):
426
+        if self.has_limit():
427
+            return self.modes[l]
428
+        else:
429
+            return None
430
+
431
+    def has_key(self):
432
+        return self.has_mode("k")
433
+
434
+    def key(self):
435
+        if self.has_key():
436
+            return self.modes["k"]
437
+        else:
438
+            return None

+ 64 - 0
irccat View File

@@ -0,0 +1,64 @@
1
+#! /usr/bin/env python
2
+#
3
+# Example program using irclib.py.
4
+#
5
+# This program is free without restrictions; do anything you like with
6
+# it.
7
+#
8
+# Joel Rosdahl <joel@rosdahl.net>
9
+
10
+import irclib
11
+import sys
12
+
13
+def on_connect(connection, event):
14
+    if irclib.is_channel(target):
15
+        connection.join(target)
16
+    else:
17
+        while 1:
18
+            line = sys.stdin.readline()
19
+            if not line:
20
+                break
21
+            connection.privmsg(target, line)
22
+        connection.quit("Using irclib.py")
23
+
24
+def on_join(connection, event):
25
+    while 1:
26
+        line = sys.stdin.readline()
27
+        if not line:
28
+            break
29
+        connection.privmsg(target, line)
30
+    connection.quit("Using irclib.py")
31
+
32
+if len(sys.argv) != 4:
33
+    print "Usage: irccat <server[:port]> <nickname> <target>"
34
+    print "\ntarget is a nickname or a channel."
35
+    sys.exit(1)
36
+
37
+def on_disconnect(connection, event):
38
+    sys.exit(0)
39
+
40
+s = sys.argv[1].split(":", 1)
41
+server = s[0]
42
+if len(s) == 2:
43
+    try:
44
+        port = int(s[1])
45
+    except ValueError:
46
+        print "Error: Erroneous port."
47
+        sys.exit(1)
48
+else:
49
+    port = 6667
50
+nickname = sys.argv[2]
51
+target = sys.argv[3]
52
+
53
+irc = irclib.IRC()
54
+try:
55
+    c = irc.server().connect(server, port, nickname)
56
+except irclib.ServerConnectionError, x:
57
+    print x
58
+    sys.exit(1)
59
+
60
+c.add_global_handler("welcome", on_connect)
61
+c.add_global_handler("join", on_join)
62
+c.add_global_handler("disconnect", on_disconnect)
63
+
64
+irc.process_forever()

+ 66 - 0
irccat2 View File

@@ -0,0 +1,66 @@
1
+#! /usr/bin/env python
2
+#
3
+# Example program using irclib.py.
4
+#
5
+# This program is free without restrictions; do anything you like with
6
+# it.
7
+#
8
+# Joel Rosdahl <joel@rosdahl.net>
9
+
10
+import irclib
11
+import sys
12
+
13
+class IRCCat(irclib.SimpleIRCClient):
14
+    def __init__(self, target):
15
+        irclib.SimpleIRCClient.__init__(self)
16
+        self.target = target
17
+
18
+    def on_welcome(self, connection, event):
19
+        if irclib.is_channel(self.target):
20
+            connection.join(self.target)
21
+        else:
22
+            self.send_it()
23
+
24
+    def on_join(self, connection, event):
25
+        self.send_it()
26
+
27
+    def on_disconnect(self, connection, event):
28
+        sys.exit(0)
29
+
30
+    def send_it(self):
31
+        while 1:
32
+            line = sys.stdin.readline()
33
+            if not line:
34
+                break
35
+            self.connection.privmsg(self.target, line)
36
+        self.connection.quit("Using irclib.py")
37
+
38
+def main():
39
+    if len(sys.argv) != 4:
40
+        print "Usage: irccat2 <server[:port]> <nickname> <target>"
41
+        print "\ntarget is a nickname or a channel."
42
+        sys.exit(1)
43
+
44
+    s = sys.argv[1].split(":", 1)
45
+    server = s[0]
46
+    if len(s) == 2:
47
+        try:
48
+            port = int(s[1])
49
+        except ValueError:
50
+            print "Error: Erroneous port."
51
+            sys.exit(1)
52
+    else:
53
+        port = 6667
54
+    nickname = sys.argv[2]
55
+    target = sys.argv[3]
56
+
57
+    c = IRCCat(target)
58
+    try:
59
+        c.connect(server, port, nickname)
60
+    except irclib.ServerConnectionError, x:
61
+        print x
62
+        sys.exit(1)
63
+    c.start()
64
+
65
+if __name__ == "__main__":
66
+    main()

File diff suppressed because it is too large
+ 1560 - 0
irclib.py


+ 74 - 0
python-irclib.spec View File

@@ -0,0 +1,74 @@
1
+Summary: A set of Python modules for IRC support.
2
+Name: python-irclib
3
+Version: 0.4.8
4
+Release: 1
5
+Group: Development/Libraries
6
+License: LGPL
7
+URL: http://python-irclib.sourceforge.net
8
+Source: %{name}-%{version}.tar.gz
9
+BuildRoot: %{_tmppath}/%{name}-root
10
+Requires: python
11
+BuildPrereq: python
12
+BuildArch: noarch
13
+
14
+%description
15
+This library is intended to encapsulate the IRC protocol at a quite
16
+low level.  It provides an event-driven IRC client framework.  It has
17
+a fairly thorough support for the basic IRC protocol, CTCP and DCC
18
+connections.
19
+
20
+%prep
21
+%setup -q
22
+chmod 644 *
23
+
24
+%build
25
+python -c "import py_compile; py_compile.compile('irclib.py')"
26
+python -c "import py_compile; py_compile.compile('ircbot.py')"
27
+
28
+%install
29
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
30
+%{__mkdir_p} $RPM_BUILD_ROOT/usr/lib/python1.5/site-packages
31
+%{__install} -m 644 irclib.py* $RPM_BUILD_ROOT/usr/lib/python1.5/site-packages
32
+%{__install} -m 644 ircbot.py* $RPM_BUILD_ROOT/usr/lib/python1.5/site-packages
33
+
34
+%clean
35
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
36
+
37
+%files
38
+%defattr(-,root,root)
39
+%doc README ChangeLog COPYING irccat irccat2 servermap testbot.py dccsend dccreceive
40
+/usr/lib/python*/site-packages/*
41
+
42
+%changelog
43
+* Sat Sep 11 2008 Keltus <keltus@users.sourceforge.net> 0.4.8-1
44
+- upgraded to 0.4.8
45
+
46
+* Sat Aug 29 2008 Keltus <keltus@users.sourceforge.net> 0.4.7-1
47
+- upgraded to 0.4.7
48
+
49
+* Sat Dec 24 2005 Keltus <keltus@users.sourceforge.net> 0.4.6-1
50
+- upgraded to 0.4.6
51
+
52
+* Wed May 18 2005 Keltus <keltus@users.sourceforge.net> 0.4.5-1
53
+- upgraded to 0.4.5
54
+
55
+* Wed Feb 23 2005 Keltus <keltus@users.sourceforge.net> 0.4.4-1
56
+- upgraded to 0.4.4
57
+
58
+* Sun Jan 19 2005 Joel Rosdahl <joel@rosdahl.net> 0.4.3-1
59
+- upgraded to 0.4.3
60
+
61
+* Fri Jul  9 2004 Joel Rosdahl <joel@rosdahl.net> 0.4.2-1
62
+- upgraded to 0.4.2
63
+
64
+* Thu Oct 30 2003 Joel Rosdahl <joel@rosdahl.net> 0.4.1-1
65
+- upgraded to 0.4.1
66
+
67
+* Mon Sep  1 2002 Gary Benson <gary@inauspicious.org> 0.4.0-1
68
+- upgraded to 0.4.0
69
+
70
+* Wed Feb 20 2002 Gary Benson <gary@inauspicious.org> 0.3.4-1
71
+- upgraded to 0.3.4
72
+
73
+* Wed Feb 20 2002 Gary Benson <gary@inauspicious.org> 0.3.3-1
74
+- initial revision

+ 164 - 0
servermap View File

@@ -0,0 +1,164 @@
1
+#! /usr/bin/env python
2
+#
3
+# Example program using irclib.py.
4
+#
5
+# Copyright (C) 1999-2002  Joel Rosdahl
6
+#
7
+# This library is free software; you can redistribute it and/or
8
+# modify it under the terms of the GNU Lesser General Public
9
+# License as published by the Free Software Foundation; either
10
+# version 2.1 of the License, or (at your option) any later version.
11
+#
12
+# This library is distributed in the hope that it will be useful,
13
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
+# Lesser General Public License for more details.
16
+#
17
+# You should have received a copy of the GNU Lesser General Public
18
+# License along with this library; if not, write to the Free Software
19
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
20
+#
21
+# Joel Rosdahl <joel@rosdahl.net>
22
+#
23
+# servermap connects to an IRC server and finds out what other IRC
24
+# servers there are in the net and prints a tree-like map of their
25
+# interconnections.
26
+#
27
+# Example:
28
+#
29
+# % ./servermap irc.dal.net somenickname
30
+# Connecting to server...
31
+# Getting links...
32
+#
33
+# 26 servers (18 leaves and 8 hubs)
34
+#
35
+# splitrock.tx.us.dal.net
36
+# `-vader.ny.us.dal.net
37
+#   |-twisted.ma.us.dal.net
38
+#   |-sodre.nj.us.dal.net
39
+#   |-glass.oh.us.dal.net
40
+#   |-distant.ny.us.dal.net
41
+#   | |-algo.se.eu.dal.net
42
+#   | | |-borg.se.eu.dal.net
43
+#   | | | `-ced.se.eu.dal.net
44
+#   | | |-viking.no.eu.dal.net
45
+#   | | |-inco.fr.eu.dal.net
46
+#   | | |-paranoia.se.eu.dal.net
47
+#   | | |-gaston.se.eu.dal.net
48
+#   | | | `-powertech.no.eu.dal.net
49
+#   | | `-algo-u.se.eu.dal.net
50
+#   | |-philly.pa.us.dal.net
51
+#   | |-liberty.nj.us.dal.net
52
+#   | `-jade.va.us.dal.net
53
+#   `-journey.ca.us.dal.net
54
+#     |-ion.va.us.dal.net
55
+#     |-dragons.ca.us.dal.net
56
+#     |-toronto.on.ca.dal.net
57
+#     | `-netropolis-r.uk.eu.dal.net
58
+#     |   |-traced.de.eu.dal.net
59
+#     |   `-lineone.uk.eu.dal.net
60
+#     `-omega.ca.us.dal.net
61
+
62
+import irclib
63
+import sys
64
+
65
+if len(sys.argv) != 3:
66
+    print "Usage: servermap <server[:port]> <nickname>"
67
+    sys.exit(1)
68
+
69
+links = []
70
+
71
+def on_connect(connection, event):
72
+    sys.stdout.write("\nGetting links...")
73
+    sys.stdout.flush()
74
+    connection.links()
75
+
76
+def on_passwdmismatch(connection, event):
77
+    print "Password required."
78
+    sys.exit(1)
79
+
80
+def on_links(connection, event):
81
+    global links
82
+
83
+    links.append((event.arguments()[0],
84
+                  event.arguments()[1],
85
+                  event.arguments()[2]))
86
+
87
+def on_endoflinks(connection, event):
88
+    global links
89
+
90
+    print "\n"
91
+
92
+    m = {}
93
+    for (to_node, from_node, desc) in links:
94
+        if from_node != to_node:
95
+            m[from_node] = m.get(from_node, []) + [to_node]
96
+
97
+    if connection.get_server_name() in m:
98
+        if len(m[connection.get_server_name()]) == 1:
99
+            hubs = len(m) - 1
100
+        else:
101
+            hubs = len(m)
102
+    else:
103
+        hubs = 0
104
+
105
+    print "%d servers (%d leaves and %d hubs)\n" % (len(links), len(links)-hubs, hubs)
106
+
107
+    print_tree(0, [], connection.get_server_name(), m)
108
+    connection.quit("Using irclib.py")
109
+
110
+def on_disconnect(connection, event):
111
+    sys.exit(0)
112
+
113
+def indent_string(level, active_levels, last):
114
+    if level == 0:
115
+        return ""
116
+    s = ""
117
+    for i in range(level-1):
118
+        if i in active_levels:
119
+            s = s + "| "
120
+        else:
121
+            s = s + "  "
122
+    if last:
123
+        s = s + "`-"
124
+    else:
125
+        s = s + "|-"
126
+    return s
127
+
128
+def print_tree(level, active_levels, root, map, last=0):
129
+    sys.stdout.write(indent_string(level, active_levels, last)
130
+                     + root + "\n")
131
+    if root in map:
132
+        list = map[root]
133
+        for r in list[:-1]:
134
+            print_tree(level+1, active_levels[:]+[level], r, map)
135
+        print_tree(level+1, active_levels[:], list[-1], map, 1)
136
+
137
+s = sys.argv[1].split(":", 1)
138
+server = s[0]
139
+if len(s) == 2:
140
+    try:
141
+        port = int(s[1])
142
+    except ValueError:
143
+        print "Error: Erroneous port."
144
+        sys.exit(1)
145
+else:
146
+    port = 6667
147
+nickname = sys.argv[2]
148
+
149
+irc = irclib.IRC()
150
+sys.stdout.write("Connecting to server...")
151
+sys.stdout.flush()
152
+try:
153
+    c = irc.server().connect(server, port, nickname)
154
+except irclib.ServerConnectionError, x:
155
+    print x
156
+    sys.exit(1)
157
+
158
+c.add_global_handler("welcome", on_connect)
159
+c.add_global_handler("passwdmismatch", on_passwdmismatch)
160
+c.add_global_handler("links", on_links)
161
+c.add_global_handler("endoflinks", on_endoflinks)
162
+c.add_global_handler("disconnect", on_disconnect)
163
+
164
+irc.process_forever()

+ 9 - 0
setup.py View File

@@ -0,0 +1,9 @@
1
+#! /usr/bin/env python
2
+
3
+from distutils.core import setup
4
+setup(name="python-irclib",
5
+      version="0.4.8",
6
+      py_modules=["irclib", "ircbot"],
7
+      author="Joel Rosdahl",
8
+      author_email="joel@rosdahl.net",
9
+      url="http://python-irclib.sourceforge.net")

+ 118 - 0
testbot.py View File

@@ -0,0 +1,118 @@
1
+#! /usr/bin/env python
2
+#
3
+# Example program using ircbot.py.
4
+#
5
+# Joel Rosdahl <joel@rosdahl.net>
6
+
7
+"""A simple example bot.
8
+
9
+This is an example bot that uses the SingleServerIRCBot class from
10
+ircbot.py.  The bot enters a channel and listens for commands in
11
+private messages and channel traffic.  Commands in channel messages
12
+are given by prefixing the text by the bot name followed by a colon.
13
+It also responds to DCC CHAT invitations and echos data sent in such
14
+sessions.
15
+
16
+The known commands are:
17
+
18
+    stats -- Prints some channel information.
19
+
20
+    disconnect -- Disconnect the bot.  The bot will try to reconnect
21
+                  after 60 seconds.
22
+
23
+    die -- Let the bot cease to exist.
24
+
25
+    dcc -- Let the bot invite you to a DCC CHAT connection.
26
+"""
27
+
28
+from ircbot import SingleServerIRCBot
29
+from irclib import nm_to_n, nm_to_h, irc_lower, ip_numstr_to_quad, ip_quad_to_numstr
30
+
31
+class TestBot(SingleServerIRCBot):
32
+    def __init__(self, channel, nickname, server, port=6667):
33
+        SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
34
+        self.channel = channel
35
+
36
+    def on_nicknameinuse(self, c, e):
37
+        c.nick(c.get_nickname() + "_")
38
+
39
+    def on_welcome(self, c, e):
40
+        c.join(self.channel)
41
+
42
+    def on_privmsg(self, c, e):
43
+        self.do_command(e, e.arguments()[0])
44
+
45
+    def on_pubmsg(self, c, e):
46
+        a = e.arguments()[0].split(":", 1)
47
+        if len(a) > 1 and irc_lower(a[0]) == irc_lower(self.connection.get_nickname()):
48
+            self.do_command(e, a[1].strip())
49
+        return
50
+
51
+    def on_dccmsg(self, c, e):
52
+        c.privmsg("You said: " + e.arguments()[0])
53
+
54
+    def on_dccchat(self, c, e):
55
+        if len(e.arguments()) != 2:
56
+            return
57
+        args = e.arguments()[1].split()
58
+        if len(args) == 4:
59
+            try:
60
+                address = ip_numstr_to_quad(args[2])
61
+                port = int(args[3])
62
+            except ValueError:
63
+                return
64
+            self.dcc_connect(address, port)
65
+
66
+    def do_command(self, e, cmd):
67
+        nick = nm_to_n(e.source())
68
+        c = self.connection
69
+
70
+        if cmd == "disconnect":
71
+            self.disconnect()
72
+        elif cmd == "die":
73
+            self.die()
74
+        elif cmd == "stats":
75
+            for chname, chobj in self.channels.items():
76
+                c.notice(nick, "--- Channel statistics ---")
77
+                c.notice(nick, "Channel: " + chname)
78
+                users = chobj.users()
79
+                users.sort()
80
+                c.notice(nick, "Users: " + ", ".join(users))
81
+                opers = chobj.opers()
82
+                opers.sort()
83
+                c.notice(nick, "Opers: " + ", ".join(opers))
84
+                voiced = chobj.voiced()
85
+                voiced.sort()
86
+                c.notice(nick, "Voiced: " + ", ".join(voiced))
87
+        elif cmd == "dcc":
88
+            dcc = self.dcc_listen()
89
+            c.ctcp("DCC", nick, "CHAT chat %s %d" % (
90
+                ip_quad_to_numstr(dcc.localaddress),
91
+                dcc.localport))
92
+        else:
93
+            c.notice(nick, "Not understood: " + cmd)
94
+
95
+def main():
96
+    import sys
97
+    if len(sys.argv) != 4:
98
+        print "Usage: testbot <server[:port]> <channel> <nickname>"
99
+        sys.exit(1)
100
+
101
+    s = sys.argv[1].split(":", 1)
102
+    server = s[0]
103
+    if len(s) == 2:
104
+        try:
105
+            port = int(s[1])
106
+        except ValueError:
107
+            print "Error: Erroneous port."
108
+            sys.exit(1)
109
+    else:
110
+        port = 6667
111
+    channel = sys.argv[2]
112
+    nickname = sys.argv[3]
113
+
114
+    bot = TestBot(channel, nickname, server, port)
115
+    bot.start()
116
+
117
+if __name__ == "__main__":
118
+    main()