From 9e6e30324fc0acf923be1a7a77a8dd26fe2add3f Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 14 Oct 2016 21:29:36 -0700 Subject: [PATCH 01/12] setup: reword fallback version format & warnings Also, change the suffix from -dirty to -nogit. (cherry picked from commit a4e1f2a4ab78bd8511378088ef785a397e76ad02) --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 8e81522..10e62dc 100644 --- a/setup.py +++ b/setup.py @@ -19,8 +19,9 @@ with open('VERSION', encoding='utf-8') as f: try: real_version = subprocess.check_output(['git', 'describe', '--tags']).decode('utf-8').strip() except Exception as e: - print('ERROR: Failed to get Git version from "git describe --tags": %s: %s' % (type(e).__name__, e)) - real_version = version + '-dirty' + print('WARNING: Failed to get Git version from "git describe --tags": %s: %s' % (type(e).__name__, e)) + print("If you're installing from PyPI or a tarball, ignore the above message.") + real_version = version + '-nogit' # Write the version to disk. with open('__init__.py', 'w') as f: From eb6419022804058a946757524bca4ff1f08c18e3 Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 7 Oct 2016 21:08:55 -0700 Subject: [PATCH 02/12] Clientbot: use a more specific realname fallback (cherry picked from commit 288a2fffd79d2f34a3af36fbf222bf8fd9d7641c) This is cherry-picked as a prerequisite for the next commit. --- protocols/clientbot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/protocols/clientbot.py b/protocols/clientbot.py index abe2d10..cba40da 100644 --- a/protocols/clientbot.py +++ b/protocols/clientbot.py @@ -6,6 +6,7 @@ from pylinkirc import utils, conf from pylinkirc.log import log from pylinkirc.classes import Protocol, IrcUser, IrcServer +FALLBACK_REALNAME = 'PyLink Relay Mirror Client' COMMON_PREFIXMODES = [('h', 'halfop'), ('a', 'admin'), ('q', 'owner'), ('y', 'owner')] class ClientbotWrapperProtocol(Protocol): @@ -313,7 +314,7 @@ class ClientbotWrapperProtocol(Protocol): if (not idsource) and self.irc.pseudoclient: # We don't know the sender, so it most be new. - idsource = self.spawnClient(nick, ident, host, server=self.irc.uplink).uid + idsource = self.spawnClient(nick, ident, host, server=self.irc.uplink, realname=FALLBACK_REALNAME).uid try: func = getattr(self, 'handle_'+command.lower()) @@ -402,7 +403,7 @@ class ClientbotWrapperProtocol(Protocol): # Get the PUID for the given nick. If one doesn't exist, spawn # a new virtual user. TODO: wait for WHO responses for each nick before # spawning in order to get a real ident/host. - idsource = self.irc.nickToUid(nick) or self.spawnClient(nick, server=self.irc.uplink).uid + idsource = self.irc.nickToUid(nick) or self.spawnClient(nick, server=self.irc.uplink, realname=FALLBACK_REALNAME).uid # Queue these virtual users to be joined if they're not already in the channel, # or we're waiting for a kick acknowledgment for them. From 405b886ba2b6152b0212901f0b9b7ab4660b1ef7 Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 14 Oct 2016 22:29:13 -0700 Subject: [PATCH 03/12] clientbot: overload _getUid() to deal with nick collisions between virtual clients and Clientbot users Closes #327. (cherry picked from commit 05e2d6d060de5cc3a04712c74df7f377cafbf2d5) --- protocols/clientbot.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/protocols/clientbot.py b/protocols/clientbot.py index cba40da..0cdf039 100644 --- a/protocols/clientbot.py +++ b/protocols/clientbot.py @@ -283,6 +283,27 @@ class ClientbotWrapperProtocol(Protocol): else: return # Nothing changed + def _getUid(self, nick, ident='unknown', host='unknown.host'): + """ + Fetches the UID for the given nick, creating one if it does not already exist. + + Limited (internal) nick collision checking is done here to prevent Clientbot users from + being confused with virtual clients, and vice versa.""" + # If this sender isn't known or it is one of our virtual clients, spawn a new one. + # spawnClient() will take care of any nick collisions caused by new, Clientbot users + # taking the same nick as one of our virtual clients. + idsource = self.irc.nickToUid(nick) + is_internal = self.irc.isInternalClient(idsource) + + if (not idsource) or (is_internal and self.irc.pseudoclient and idsource != self.irc.pseudoclient.uid): + if idsource: + log.debug('(%s) Nick-colliding virtual client %s/%s', self.irc.name, idsource, nick) + self.irc.callHooks([self.irc.sid, 'CLIENTBOT_NICKCOLLIDE', {'target': idsource, 'parse_as': 'SAVE'}]) + + idsource = self.spawnClient(nick, ident, host, server=self.irc.uplink, realname=FALLBACK_REALNAME).uid + + return idsource + def handle_events(self, data): """Event handler for the RFC1459/2812 (clientbot) protocol.""" data = data.split(" ") @@ -310,11 +331,7 @@ class ClientbotWrapperProtocol(Protocol): else: # Sender is a nick!user@host prefix. Split it into its relevant parts. nick, ident, host = utils.splitHostmask(sender) - idsource = self.irc.nickToUid(nick) - - if (not idsource) and self.irc.pseudoclient: - # We don't know the sender, so it most be new. - idsource = self.spawnClient(nick, ident, host, server=self.irc.uplink, realname=FALLBACK_REALNAME).uid + idsource = self._getUid(nick, ident, host) try: func = getattr(self, 'handle_'+command.lower()) @@ -403,7 +420,7 @@ class ClientbotWrapperProtocol(Protocol): # Get the PUID for the given nick. If one doesn't exist, spawn # a new virtual user. TODO: wait for WHO responses for each nick before # spawning in order to get a real ident/host. - idsource = self.irc.nickToUid(nick) or self.spawnClient(nick, server=self.irc.uplink, realname=FALLBACK_REALNAME).uid + idsource = self._getUid(nick) # Queue these virtual users to be joined if they're not already in the channel, # or we're waiting for a kick acknowledgment for them. @@ -631,8 +648,9 @@ class ClientbotWrapperProtocol(Protocol): if utils.isChannel(target): target = self.irc.toLower(target) else: - target = self._getUid(target) - return {'target': target, 'text': args[1]} + target = self.irc.nickToUid(target) + if target: + return {'target': target, 'text': args[1]} def handle_quit(self, source, command, args): """Handles incoming QUITs.""" From a09ec494f62cd6a66b24f4525cf1880c28e67498 Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 14 Oct 2016 22:39:03 -0700 Subject: [PATCH 04/12] README: cherry-pick updates from the devel branch Squashed commit of the following: commit 00279a148abe5f1f5413116b7736f758883c8287 Author: James Lu Date: Mon Oct 10 15:55:36 2016 -0700 README: update clientbot notes (cherry picked from commit 0db194726318ce2bb46b454ebe792b3896f4b80c) commit 33cd90c2553977f17e61006f29288abbe9fe5cac Author: James Lu Date: Mon Oct 10 15:54:30 2016 -0700 README: update IRCd notes (cherry picked from commit 44d139f610f51d51bd59b00015fa75ad9548ee4c) commit 639e185977e8cfe98932310d132751ea9d720609 Author: James Lu Date: Sun Sep 25 19:32:00 2016 -0700 README: briefly mention protocols/clientbot (cherry picked from commit 1fbd9edc3b9601841b06d94aca907ea27fcab677) --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 40e3248..cf072ed 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ First, make sure the following dependencies are met: These IRCds (in alphabetical order) are frequently tested and well supported. If any issues occur, please file a bug on the issue tracker. -* [charybdis](http://charybdis.io/) (3.5+ / git master) - module `ts6` +* [charybdis](http://charybdis.io/) (3.5+) - module `ts6` * [InspIRCd](http://www.inspircd.org/) 2.0.x - module `inspircd` - For vHost setting to work, `m_chghost.so` must be loaded. - Supported channel, user, and prefix modes are negotiated on connect, but hotloading modules that change these is not supported. After changing module configuration, it is recommended to SQUIT PyLink to force a protocol renegotiation. @@ -78,7 +78,7 @@ These IRCds (in alphabetical order) are frequently tested and well supported. If Support for these IRCds exist, but are not tested as frequently and thoroughly. Bugs should be filed if there are any issues, though they may not always be fixed in a timely fashion. * [Elemental-IRCd](https://github.com/Elemental-IRCd/elemental-ircd) (6.6.x / git master) - module `ts6` -* [InspIRCd](http://www.inspircd.org/) 2.2 (git master) - module `inspircd` +* [InspIRCd](http://www.inspircd.org/) 3.0.x (git master) - module `inspircd` * [IRCd-Hybrid](http://www.ircd-hybrid.org/) (8.2.x / svn trunk) - module `hybrid` - Note: for host changing support and optimal functionality, a `service{}` block / U-line should be added for PyLink on every IRCd across your network. * [juno-ircd](https://github.com/cooper/yiria) (11.x / janet) - module `ts6` (see [configuration example](https://github.com/cooper/juno/blob/master/doc/ts6.md#pylink)) @@ -87,3 +87,9 @@ Support for these IRCds exist, but are not tested as frequently and thoroughly. - For optimal functionality (mode overrides in relay, etc.), consider adding `UWorld{}` blocks / U-lines for every server that PyLink spawns. Other TS6 and P10 variations may work, but are not officially supported. + +### Clientbot + +Since v1.0, PyLink supports connecting to IRCds as a relay bot and forwarding users back, similar to Janus' Clientbot. This can be useful if the IRCd a network used isn't supported, or if you want to relay certain channels without fully linking with a network. + +For Relay to work properly with Clientbot, be sure to load the `relay_clientbot` plugin in conjunction with `relay`. From ac270c200c820f42dd829a9dd4924b7a9512ccd1 Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 14 Oct 2016 22:51:33 -0700 Subject: [PATCH 05/12] PyLink 1.0.2 --- RELNOTES.md | 17 +++++++++++++++++ VERSION | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/RELNOTES.md b/RELNOTES.md index bfd74d7..0235b31 100644 --- a/RELNOTES.md +++ b/RELNOTES.md @@ -1,3 +1,20 @@ +# PyLink 1.0.2 +Tagged as **1.0.2** by [GLolol](https://github.com/GLolol) + +The "Baluga" release. + +### Changes from 1.0.1 + +#### Bug fixes +- Clientbot: Fixed nick collisions between virtual clients and real users (#327) +- Fix typo in example conf that caused `log::filerotation` to become an empty, `None`-valued block. This in turn caused the `log` module to crash. + +#### Feature changes +- Clientbot now uses a more specific realname fallback ("PyLink Relay Mirror Client") instead of potentially misleading text such as "PyLink Service Client". In the future, this text may be made configurable. + +#### Internal fixes / improvements + - setup.py: reworded warnings if `git describe --tags` fails / fallback version is used. Also, the internal VCS version for non-Git builds is now `-nogit` instead of `-dirty`. + # PyLink 1.0.1 Tagged as **1.0.1** by [GLolol](https://github.com/GLolol) diff --git a/VERSION b/VERSION index 7dea76e..6d7de6e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.1 +1.0.2 From 2ed8b68c444e6b00c3f7251c5f11c68b98d4ea95 Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 23 Sep 2016 22:49:04 -0700 Subject: [PATCH 06/12] relay: allow configuring custom relay server suffixes Closes #333. (cherry picked from commit 39008334584023ddc540f7f62e45e7910ecd6783) --- example-conf.yml | 4 ++++ plugins/relay.py | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/example-conf.yml b/example-conf.yml index 9656db4..13c1a9e 100644 --- a/example-conf.yml +++ b/example-conf.yml @@ -477,6 +477,10 @@ relay: # False. allow_clientbot_pms: false + # Sets the suffix that relay subservers should use. Defaults to "relay" (as in net1.relay, + # net2.relay, etc.) if not specified. + #server_suffix: "relay.yournet.net" + games: # Sets the nick of the Games service, if you're using it. This defaults to "games" if not defined. nick: Games diff --git a/plugins/relay.py b/plugins/relay.py index 6174f25..5483730 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -252,7 +252,10 @@ def spawnRelayServer(irc, remoteirc): try: # ENDBURST is delayed by 3 secs on supported IRCds to prevent # triggering join-flood protection and the like. - sid = irc.proto.spawnServer('%s.relay' % remoteirc.name, + suffix = conf.conf.get('relay', {}).get('server_suffix', 'relay') + # Strip any leading or trailing .'s + suffix = suffix.strip('.') + sid = irc.proto.spawnServer('%s.%s' % (remoteirc.name, suffix), desc="PyLink Relay network - %s" % (remoteirc.serverdata.get('netname')\ or remoteirc.name), endburst_delay=3) From 9f4c68f114827b24ae79dceeae6b65b37ba53351 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sat, 22 Oct 2016 20:45:29 -0700 Subject: [PATCH 07/12] relay: skip channel TS check for Clientbot (cherry picked from commit d230af1d5e3e14a12dc267bbd66b1bcf219e0ae9) --- plugins/relay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/relay.py b/plugins/relay.py index 5483730..3a5d80c 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -1681,7 +1681,7 @@ def link(irc, source, args): our_ts = irc.channels[localchan].ts their_ts = world.networkobjects[remotenet].channels[channel].ts - if our_ts < their_ts: + if (our_ts < their_ts) and irc.protoname != 'clientbot': log.debug('(%s) relay: Blocking link request %s%s -> %s%s due to bad TS (%s < %s)', irc.name, irc.name, localchan, remotenet, channel, our_ts, their_ts) irc.reply("Error: the channel creation date (TS) on %s is lower than the target " From 72818412e18c3b2136afa9a2f26f543df891cc36 Mon Sep 17 00:00:00 2001 From: James Lu Date: Thu, 27 Oct 2016 20:50:10 -0700 Subject: [PATCH 08/12] faq: fix link to dependencies list --- docs/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index e4d26e0..edbcbc9 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -2,7 +2,7 @@ ### I get errors like "ImportError: No module named 'yaml'" when I start PyLink -You are missing dependencies - re-read https://github.com/GLolol/PyLink#dependencies +You are missing dependencies - re-read https://github.com/GLolol/PyLink/blob/master/README.md#installation ### I get errors like "yaml.scanner.ScannerError: while scanning for the next token, found character '\t' that cannot start any token" From e0802192f652746bb1ab4f97b50f84ad9fd8276a Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 28 Oct 2016 20:04:39 -0700 Subject: [PATCH 09/12] README: add Debian repository instructions --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index cf072ed..92bd1c5 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ You can also find support via our IRC channels: `#PyLink @ irc.overdrivenetworks ## Installation +### Installing via Debian APT repository (beta; stable branch only) + +The Utopia Repository hosts `.deb` packages for PyLink. For Debian Jessie (stable) and Stretch/sid (testing), the `pylink` package and its dependencies are available in the `main` section. See https://packages.overdrivenetworks.com/#instructions for setup instructions. + +Upon installing `pylink`, example configuration and docs will be in `/usr/share/doc/pylink/examples` and `/usr/share/doc/pylink/docs` respectively. You can also install a local copy of the [PyLink API reference](https://pylink.github.io/), which is provided by the `pylink-doc` package. + ### Installing from source First, make sure the following dependencies are met: From 441bf5f048a6884bdf566e3a1101a26d7deefca8 Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 28 Oct 2016 20:05:35 -0700 Subject: [PATCH 10/12] README: link to utopia repository site --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92bd1c5..0b3782b 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ You can also find support via our IRC channels: `#PyLink @ irc.overdrivenetworks ### Installing via Debian APT repository (beta; stable branch only) -The Utopia Repository hosts `.deb` packages for PyLink. For Debian Jessie (stable) and Stretch/sid (testing), the `pylink` package and its dependencies are available in the `main` section. See https://packages.overdrivenetworks.com/#instructions for setup instructions. +[The Utopia Repository](https://packages.overdrivenetworks.com/) hosts `.deb` packages for PyLink. For Debian Jessie (stable) and Stretch/sid (testing), the `pylink` package and its dependencies are available in the `main` section. See https://packages.overdrivenetworks.com/#instructions for setup instructions. Upon installing `pylink`, example configuration and docs will be in `/usr/share/doc/pylink/examples` and `/usr/share/doc/pylink/docs` respectively. You can also install a local copy of the [PyLink API reference](https://pylink.github.io/), which is provided by the `pylink-doc` package. From 9950e0948f3aaa1f9948fc7eb89a22a29855b464 Mon Sep 17 00:00:00 2001 From: James Lu Date: Wed, 2 Nov 2016 22:23:45 -0700 Subject: [PATCH 11/12] conf: split off absolute paths in confname This fixes invalid database names such as "automode-/tmp/test.db" from being generated when PyLink is started with an absolute path to its config. Closes #358. --- conf.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 2ae379f..7d1e213 100644 --- a/conf.py +++ b/conf.py @@ -11,6 +11,7 @@ except ImportError: raise ImportError("Please install PyYAML and try again.") import sys +import os.path from collections import defaultdict from . import world @@ -58,8 +59,10 @@ def validateConf(conf): def loadConf(filename, errors_fatal=True): """Loads a PyLink configuration file from the filename given.""" global confname, conf, fname + # Note: store globally the last loaded conf filename, for REHASH in coremods/control. fname = filename - confname = filename.split('.', 1)[0] + # For the internal config name, strip off any .yml extensions and absolute paths + confname = os.path.basename(filename).split('.', 1)[0] try: with open(filename, 'r') as f: conf = yaml.load(f) From 9f43c0fe1784fffd4428bdd1a1d3f8690af28c1c Mon Sep 17 00:00:00 2001 From: James Lu Date: Wed, 2 Nov 2016 22:26:47 -0700 Subject: [PATCH 12/12] automode: fix typo in DB error message --- plugins/automode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/automode.py b/plugins/automode.py index bf01b9f..4ae70f2 100644 --- a/plugins/automode.py +++ b/plugins/automode.py @@ -35,7 +35,7 @@ def loadDB(): with open(dbname, "r") as f: db.update(json.load(f)) except (ValueError, IOError, OSError): - log.info("Automode: failed to load links database %s; creating a new one in " + log.info("Automode: failed to load ACL database %s; creating a new one in " "memory.", dbname) def exportDB():