Branch: refs/heads/master Author: Enrico Tröger enrico.troeger@uvena.de Committer: Enrico Tröger enrico.troeger@uvena.de Date: Sun, 29 May 2022 14:35:56 UTC Commit: f9b6e2d669967978984fa9185f40e9a0ee1508c2 https://github.com/geany/infrastructure/commit/f9b6e2d669967978984fa9185f40e...
Log Message: ----------- Remove old unused IRC scripts
Modified Paths: -------------- README.md ircbot-plugins/Geany/README.txt ircbot-plugins/Geany/__init__.py ircbot-plugins/Geany/config.py ircbot-plugins/Geany/plugin.py ircbot-plugins/Geany/timer.py ircbot-plugins/SupySocketServer/README.txt ircbot-plugins/SupySocketServer/__init__.py ircbot-plugins/SupySocketServer/config.py ircbot-plugins/SupySocketServer/plugin.py scripts/git2irc/git2irc.conf scripts/git2irc/git2irc.py scripts/irclog.py
Modified: README.md 21 lines changed, 2 insertions(+), 19 deletions(-) =================================================================== @@ -1,30 +1,24 @@ Geany Infrastructure Scripts ============================
- The scripts in this repository are used for various purposes on geany.org.
-Basically they provide some additional and cool functions like announcing -GIT commits to the IRC channel, maintain the GIT mirror repository and similar tasks. - +Basically they provide some additional and cool functions like generating +GIT commits emails, maintain the GIT mirror repository and similar tasks.
Add or remove a repository ==========================
If you want to add or remove a repository maintained by these scripts, follow these steps:
* Edit the following files and find relevant repository information at the head of each file: - * scripts/git2irc/git2irc.conf * scripts/git_hooks/github_commit_mail.py * scripts/git_hooks/post_commit_hook.py
* Update the infrastructure repository on geany.org (as user *geany*):
cd /home/geany/infrastructure && git pull
- * Edit /home/geany/git2irc.conf on geany:org: add/remove the repository from the - "repositories" settings at the top of the file - * Edit /usr/local/cgit/cgitrc on geany.org: at the end of the file, copy one of the existing repository stanzas and adjust the settings accordingly
@@ -56,17 +50,6 @@ If you want to add or remove a repository maintained by these scripts, follow th * Open http://git.geany.org/ in your browser and check whether the new repository is visible and has files.
- -IRC Bot Plugins -=============== - -In the directory ircbot-plugins there are two plugins for the IRC bot Supybot -(http://www.supybot.org/). - -The plugins enhance the used Supybot instance on #geany by various useful and funny -features like a bunch of !commands. For details, read the source code. - - License =============== Unless stated otherwise all code in this repository is licensed of under the terms
Modified: ircbot-plugins/Geany/README.txt 5 lines changed, 0 insertions(+), 5 deletions(-) =================================================================== @@ -1,5 +0,0 @@ -Miscellaneous fun commands we used to have in #geany on Freenode.net. - -The code is mostly a big hack and not generally usable. -It has hard-coded paths and quite special functionalities. Still, -feel free to use and/or modify it as necessary.
Modified: ircbot-plugins/Geany/__init__.py 61 lines changed, 0 insertions(+), 61 deletions(-) =================================================================== @@ -1,61 +0,0 @@ -### -# -*- coding: utf-8 -*- -# Copyright (c) 2003-2005, Jeremiah Fincher -# Copyright (c) 2010, Enrico Tröger -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions, and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions, and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the author of this software nor the name of -# contributors to this software may be used to endorse or promote products -# derived from this software without specific prior written consent. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -### - -""" -Provides various fun commands. -""" - -import supybot -import supybot.world as world - -# Use this for the version of this plugin. You may wish to put a CVS keyword -# in here if you're keeping the plugin in CVS or some similar system. -__version__ = "1.0" - -__author__ = supybot.Author('Enrico Tröger', 'eht16', - 'enrico.troeger@uvena.de') - -# This is a dictionary mapping supybot.Author instances to lists of -# contributions. -__contributors__ = {} - -import config -import plugin -reload(plugin) # In case we're being reloaded. -# Add more reloads here if you add third-party modules and want them to be -# reloaded when this plugin is reloaded. Don't forget to import them as well! - - -Class = plugin.Class -configure = config.configure - - -# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
Modified: ircbot-plugins/Geany/config.py 46 lines changed, 0 insertions(+), 46 deletions(-) =================================================================== @@ -1,46 +0,0 @@ -### -# -*- coding: utf-8 -*- -# Copyright (c) 2003-2005, Jeremiah Fincher -# Copyright (c) 2010, Enrico Tröger -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions, and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions, and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the author of this software nor the name of -# contributors to this software may be used to endorse or promote products -# derived from this software without specific prior written consent. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -### - -import supybot.conf as conf -import supybot.registry as registry - -def configure(advanced): - # This will be called by supybot to configure this module. advanced is - # a bool that specifies whether the user identified himself as an advanced - # user or not. You should effect your configuration by manipulating the - # registry as appropriate. - conf.registerPlugin('Geany', True) - - -Geany = conf.registerPlugin('Geany') - - -# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
Modified: ircbot-plugins/Geany/plugin.py 315 lines changed, 0 insertions(+), 315 deletions(-) =================================================================== @@ -1,315 +0,0 @@ -### -# -*- coding: utf-8 -*- -# Copyright (c) 2003-2005, Jeremiah Fincher -# Copyright (c) 2010, Enrico Tröger -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions, and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions, and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the author of this software nor the name of -# contributors to this software may be used to endorse or promote products -# derived from this software without specific prior written consent. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -### - -from timer import RepeatTimer - -import random -import threading -from ConfigParser import SafeConfigParser - -from supybot.commands import * -import supybot.callbacks as callbacks - -import supybot.conf as conf - - -IRC_USERLIST_FILEPATH = '/srv/tmp/irc_userlist' -GOODIES = { - 'coffee': 'A nice waiter brings %s a big cup of coffee!', - 'coke': 'A nice waiter brings %s a cool bottle of coke!', - 'pepsi': 'A nice waiter brings %s a cool bottle of Pepsi!', - 'juice': 'A nice waiter brings %s a glass of fresh juice!', - 'vodka': 'A nice waiter brings %s a shot glass of vodka!', - 'beer': 'A nice waiter brings %s a nice bottle of beer!', - 'tea': 'A nice waiter brings %s a cup of hot tea!', - 'milk': 'A nice waiter brings %s a glass of fresh, cold milk', - 'chocolate': 'A nice waiter brings %s a piece of sweet chocolate', - 'pizza': 'Someone calls Mario, and he brings %s a tasty hawaiian pizza!' -} - - -class Geany(callbacks.Plugin): - def __init__(self, irc): - self.__parent = super(Geany, self) - self.__parent.__init__(irc) - self.timer = RepeatTimer(180.0, self._write_user_list, self.log, 0, [irc]) - self.timer.start() - self.help_database = {} - self._read_help_database() - - def die(self): - if self.timer: - threading.Thread(target=self.timer.cancel).start() - - def _read_help_database(self): - config = SafeConfigParser() - config.read('help_database.rc') - for key, value in config.items('general'): - self.help_database[key] = value - - def _write_help_database(self): - conv = lambda dic: ['%s: %s' % (k, v) for (k, v) in dic.iteritems()] - data = conv(self.help_database) - data.sort() - f = open('help_database.rc', 'w') - f.write('[general]\n') - f.write('\n'.join(data)) - f.close() - - def _write_user_list(self, irc): - exclude_nicks = ['ChanServ', self._get_nick_name()] - - def filter_services(value): - return value not in exclude_nicks - - if hasattr(irc, 'getRealIrc'): - state = irc.getRealIrc().state - elif hasattr(irc, 'state'): - state = irc.state - else: - state = None - - if state: - channel_users = state.channels['#geany'].users - # filter myself and ChanServ - users = filter(filter_services, channel_users) - - f = open(IRC_USERLIST_FILEPATH, 'w') - f.write('\n'.join(users)) - f.close() - - def _get_nick_name(self): - """ - Return the configured nick name - """ - return str(conf.supybot.nick) - #~ return self.registryValue('nick') - - def _get_command_name(self, msg, fallback='help'): - """ - Parse and return the actual command name - """ - try: - cmd = msg.args[1].split()[0] - if cmd[0] == '!': - cmd = cmd[1:] - except: - cmd = fallback - return cmd - - def _process_help_request(self, irc, text): - if text == 'keywords': - keywords = sorted(self.help_database.keys()) - irc.reply(' '.join(keywords)) - return - - try: - result = self.help_database[text] - if result: - while result[0] == '@': - # read alias - # (The outer while loop could easily cause endless lookups if there are - # circular aliases defined, let's hope users stay nice.) - result = self.help_database[result[1:]] - irc.reply(result) - except KeyError: - pass - - def doPrivmsg(self, irc, msg): - (recipients, text) = msg.args - if text.startswith('?? '): - self._process_help_request(irc, text[3:]) - - def goodie(self, irc, msg, args, text): - """takes no arguments - - Request a goodie - """ - if not text: - rcpt = msg.nick - else: - text = text[0].split() - if len(text) > 1: - if text[0] == 'for': - if text[1] == 'me': - rcpt = msg.nick - else: - rcpt = text[1] - else: - rcpt = text[0] - else: - rcpt = text[0] - - cmd = self._get_command_name(msg, 'tea') - try: - irc.reply(GOODIES[cmd] % rcpt) - except KeyError: - pass - - def listgoodies(self, irc, msg, args, text): - """takes no arguments - - Lists available goodies - """ - available_goodies = sorted(GOODIES.keys()) - available_goodies = ', '.join(available_goodies) - text = 'A nice waiter offers the following goodies for you: %s' % available_goodies - irc.reply(text) - - def hello(self, irc, msg, args, text): - """takes no arguments - - Greetings - """ - text = 'Hi %s. My name is %s and I'm here to offer additional services to you! Try "?? help" for general information.' % (msg.nick, self._get_nick_name()) - irc.reply(text) - - def thanks(self, irc, msg, args, text): - """takes no arguments - - Thanks - """ - text = '%s, no problem. It was a pleasure to serve you.' % (msg.nick) - irc.reply(text) - - def test(self, irc, msg, args, text): - """takes no arguments - - Bah, tests - """ - irc.reply('I don't like tests!') - - def _learn(self, key, value): - - update = key in self.help_database - - self.help_database[key] = value - - self._write_help_database() - - return update - - def learn(self, irc, msg, args, key, value): - """newKeyword Text... - - With the command !learn you can add new keywords to the database. - Use "!learn newKeyword Text which should be added" to add new keywords. - Use this with care! - """ - update = self._learn(key, value) - - if update: - irc.reply('Existing keyword "%s" was updated' % key) - else: - irc.reply('New keyword "%s" was added' % key) - - def alias(self, irc, msg, args, dest, source): - """newWord existingWord - - Type '!alias newWord existingWord' to create a new alias, e.g. '!alias svn subversion'. - """ - if not source in self.help_database: - irc.reply('Alias "%s" could not be created because the target does not exist' % dest) - return - - update = self._learn(dest, '@%s' % source) - - if update: - irc.reply('Existing alias "%s" was updated' % dest) - else: - irc.reply('New alias "%s" was added' % dest) - - def moo(self, irc, msg, args): - """takes no arguments - - Have you mooed today? - """ - if random.randrange(0, 2): - text = """ ^__^ - (oo) - /-----(__) - / | || - * /\---/\ - ~~ ~~ -.."Have you mooed today?"..""" - for line in text.split('\n'): - irc.reply(line) - else: - irc.reply('I have Super Cow Powers. Have you mooed today?') - - def commit(self, irc, msg, args, idx): - """takes one argument, a Git ID SHA - - Type '!commit <SHA-ID-HERE>' to print a URL/link to view the commit - in Geany's online Git repository browser. - """ - idx = str(idx).lower().strip() - if all(ch in 'abcdef0123456789' for ch in idx): - irc.reply('https://github.com/geany/geany/commit/' + idx) - # using Github since it allows shortened SHAs also - #irc.reply('http://git.geany.org/geany/commit/?id=' + idx) - else: - irc.reply('Malformed Git SHA') - - # "decorate" our commands (wrap is a decorator replacement for old Python versions) - tea = wrap(goodie, [optional(many('text'))]) - coffee = wrap(goodie, [optional(many('text'))]) - coke = wrap(goodie, [optional(many('text'))]) - pepsi = wrap(goodie, [optional(many('text'))]) - juice = wrap(goodie, [optional(many('text'))]) - vodka = wrap(goodie, [optional(many('text'))]) - beer = wrap(goodie, [optional(many('text'))]) - pizza = wrap(goodie, [optional(many('text'))]) - chocolate = wrap(goodie, [optional(many('text'))]) - milk = wrap(goodie, [optional(many('text'))]) - goodies = wrap(listgoodies, [optional(many('text'))]) - goods = wrap(listgoodies, [optional(many('text'))]) - - hi = wrap(hello, [optional(many('text'))]) - hello = wrap(hello, [optional(many('text'))]) - hey = wrap(hello, [optional(many('text'))]) - - thanks = wrap(thanks, [optional(many('text'))]) - thankyou = wrap(thanks, [optional(many('text'))]) - thx = wrap(thanks, [optional(many('text'))]) - - learn = wrap(learn, ['something', 'text']) - alias = wrap(alias, ['something', 'something']) - - test = wrap(test, [optional(many('text'))]) - moo = wrap(moo) - commit = wrap(commit, ['text']) - - -Class = Geany - - -# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
Modified: ircbot-plugins/Geany/timer.py 59 lines changed, 0 insertions(+), 59 deletions(-) =================================================================== @@ -1,59 +0,0 @@ -### -# -*- coding: utf-8 -*- -# Copyright (c) 2003-2005, Jeremiah Fincher -# Copyright (c) 2010, Enrico Tröger -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions, and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions, and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the author of this software nor the name of -# contributors to this software may be used to endorse or promote products -# derived from this software without specific prior written consent. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -### - -from threading import Event, Thread - - -class RepeatTimer(Thread): - def __init__(self, interval, function, logger, iterations=0, args=[], kwargs={}): - Thread.__init__(self) - self.interval = interval - self.function = function - self.iterations = iterations - self.args = args - self.kwargs = kwargs - self.finished = Event() - self.logger = logger - - def run(self): - count = 0 - self.logger.info(u'start') - while not self.finished.isSet() and (self.iterations <= 0 or count < self.iterations): - self.finished.wait(self.interval) - if not self.finished.isSet(): - self.function(*self.args, **self.kwargs) - count += 1 - - def cancel(self): - self.logger.info(u'cancelled') - self.finished.set() - -
Modified: ircbot-plugins/SupySocketServer/README.txt 4 lines changed, 0 insertions(+), 4 deletions(-) =================================================================== @@ -1,4 +0,0 @@ - -External Control - -Version: 1.0
Modified: ircbot-plugins/SupySocketServer/__init__.py 66 lines changed, 0 insertions(+), 66 deletions(-) =================================================================== @@ -1,66 +0,0 @@ -### -# -*- coding: utf-8 -*- -# Copyright (c) 2007, Ali Afshar -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions, and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions, and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the author of this software nor the name of -# contributors to this software may be used to endorse or promote products -# derived from this software without specific prior written consent. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -### - -""" -Add a description of the plugin (to be presented to the user inside the wizard) -here. This should describe *what* the plugin does. -""" - -import supybot -import supybot.world as world - -# Use this for the version of this plugin. You may wish to put a CVS keyword -# in here if you're keeping the plugin in CVS or some similar system. -__version__ = "" - -# XXX Replace this with an appropriate author or supybot.Author instance. -__author__ = supybot.Author('Enrico Tröger', 'eht16', - 'enrico.troeger@uvena.de') - -# This is a dictionary mapping supybot.Author instances to lists of -# contributions. -__contributors__ = {} - -# This is a url where the most recent plugin package can be downloaded. -__url__ = '' # 'http://supybot.com/Members/yourname/ExternalControl/download' - -import config -import plugin -reload(plugin) # In case we're being reloaded. -# Add more reloads here if you add third-party modules and want them to be -# reloaded when this plugin is reloaded. Don't forget to import them as well! - - -Class = plugin.Class -configure = config.configure - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
Modified: ircbot-plugins/SupySocketServer/config.py 58 lines changed, 0 insertions(+), 58 deletions(-) =================================================================== @@ -1,58 +0,0 @@ -### -# Copyright (c) 2007, Ali Afshar -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions, and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions, and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the author of this software nor the name of -# contributors to this software may be used to endorse or promote products -# derived from this software without specific prior written consent. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -### - -import supybot.conf as conf -import supybot.registry as registry - -def configure(advanced): - # This will be called by supybot to configure this module. advanced is - # a bool that specifies whether the user identified himself as an advanced - # user or not. You should effect your configuration by manipulating the - # registry as appropriate. - conf.registerPlugin('SupySocketServer', True) - - -SupySocketServer = conf.registerPlugin('SupySocketServer') -# This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(ExternalControl, 'someConfigVariableName', -# registry.Boolean(False, """Help for someConfigVariableName.""")) - -conf.registerGlobalValue(SupySocketServer, 'port', - registry.Integer(7766, - """The port that the external control server - should wait for requests on.""")) - -conf.registerGlobalValue(SupySocketServer, 'host', - registry.String('localhost', - """The host that the external control server - should wait for requests on.""")) - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
Modified: ircbot-plugins/SupySocketServer/plugin.py 245 lines changed, 0 insertions(+), 245 deletions(-) =================================================================== @@ -1,245 +0,0 @@ -### -# Copyright (c) 2007, Ali Afshar -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions, and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions, and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the author of this software nor the name of -# contributors to this software may be used to endorse or promote products -# derived from this software without specific prior written consent. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -### - -import select -import threading -import socket -import SocketServer - - -import supybot.world as world -from supybot.commands import * -from supybot.log import getPluginLogger -import supybot.ircmsgs as ircmsgs -import supybot.callbacks as callbacks - - - -class RequestHandler(SocketServer.StreamRequestHandler): - - def handle(self): - # data should be: 'network channel message', e.g. - # 'Freenode #geany blah blah' - data = self.rfile.readline().strip() - self.server.logger.debug(u'got data from socket: %s' % data) - network, channel, message = data.split(' ', 2) - ci = ControlInstance() - ci.privmsg(network, channel, message) - - -class ControlInstance(object): - - def privmsg(self, network, personorchannel, message): - target_irc, target = self._get_irc_and_target(network, personorchannel) - msg = ircmsgs.privmsg(target, message) - target_irc.sendMsg(msg) - - def _get_irc(self, network): - for irc in world.ircs: - if irc.network == network: - return irc - - def _get_person_or_channel(self, irc, personorchannel): - if personorchannel.startswith('#'): - for channel in irc.state.channels: - if channel == personorchannel: - return channel - else: - return personorchannel - - def _get_irc_and_target(self, network, personorchannel): - target_irc = self._get_irc(network) - if target_irc is None: - raise Exception('Not on Network: %s' % network) - target = self._get_person_or_channel(target_irc, personorchannel) - if target is None: - raise Exception('Not on Channel: %s' % personorchannel) - return target_irc, target - - -class SocketServerImpl(SocketServer.TCPServer): - - timeout = None - allow_reuse_address = True - address_family = socket.AF_INET - socket_type = socket.SOCK_STREAM - request_queue_size = 5 - - def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): - """Constructor. May be extended, do not override.""" - SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass) - self.socket = socket.socket(self.address_family, self.socket_type) - self.__is_shut_down = threading.Event() - self.__serving = False - if bind_and_activate: - self.server_bind() - self.server_activate() - - def server_bind(self): - """Called by constructor to bind the socket. - - May be overridden. - - """ - if self.allow_reuse_address: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.socket.bind(self.server_address) - self.server_address = self.socket.getsockname() - - def server_activate(self): - """Called by constructor to activate the server. - - May be overridden. - - """ - self.socket.listen(self.request_queue_size) - - def serve_forever(self, poll_interval=0.5): - """Handle one request at a time until shutdown. - - Polls for shutdown every poll_interval seconds. Ignores - self.timeout. If you need to do periodic tasks, do them in - another thread. - """ - self.logger.info(u'listen') - self.__serving = True - self.__is_shut_down.clear() - while self.__serving: - # XXX: Consider using another file descriptor or - # connecting to the socket to wake this up instead of - # polling. Polling reduces our responsiveness to a - # shutdown request and wastes cpu at all other times. - r = select.select([self], [], [], poll_interval)[0] - if r: - self._handle_request_noblock() - self.__is_shut_down.set() - self.logger.info(u'sucessfully shut down') - - def shutdown(self): - """Stops the serve_forever loop. - - Blocks until the loop has finished. This must be called while - serve_forever() is running in another thread, or it will - deadlock. - """ - self.logger.info(u'shutdown called') - self.__serving = False - self.__is_shut_down.wait() - - def _handle_request_noblock(self): - """Handle one request, without blocking. - - I assume that select.select has returned that the socket is - readable before this function was called, so there should be - no risk of blocking in get_request(). - """ - try: - request, client_address = self.get_request() - except socket.error: - return - if self.verify_request(request, client_address): - try: - self.process_request(request, client_address) - except: - self.handle_error(request, client_address) - self.close_request(request) - - def handle_request(self): - """Handle one request, possibly blocking. - - Respects self.timeout. - """ - # Support people who used socket.settimeout() to escape - # handle_request before self.timeout was available. - timeout = self.socket.gettimeout() - if timeout is None: - timeout = self.timeout - elif self.timeout is not None: - timeout = min(timeout, self.timeout) - fd_sets = select.select([self], [], [], timeout) - if not fd_sets[0]: - self.handle_timeout() - return - self._handle_request_noblock() - - -class SupySocketServer(callbacks.Plugin): - """Add the help for "@plugin help SupySocketServer" here - This should describe *how* to use this plugin.""" - threaded = True - - def __init__(self, irc): - callbacks.Plugin.__init__(self, irc) - self._server = None - self._server_thread = None - self._start_server_in_thread() - - def _start_server_in_thread(self): - self._server_thread = threading.Thread(target=self._start_server) - self._server_thread.daemon = True - self._server_thread.start() - - def _start_server(self): - host = self.registryValue('host') - port = self.registryValue('port') - self._server = SocketServerImpl((host, port), RequestHandler) - self._server.logger = self.log - self._server.serve_forever() - - def die(self): - if self._server: - self._server.shutdown() - self._server_thread.join() - - - def outFilter(self, irc, msg): - if msg.inReplyTo: - if msg.inReplyTo.supysocketserver: - target_irc, target, notice = msg.inReplyTo.supysocketserver - self._reply_command(target_irc, target, msg, notice) - return None - else: - return msg - else: - return msg - - def _reply_command(self, target_irc, target, msg, notice): - if notice: - factory = ircmsgs.notice - else: - factory = ircmsgs.privmsg - reply_msg = factory(target, msg.args[1]) - target_irc.sendMsg(reply_msg) - - -Class = SupySocketServer - - -# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
Modified: scripts/git2irc/git2irc.conf 12 lines changed, 0 insertions(+), 12 deletions(-) =================================================================== @@ -1,12 +0,0 @@ -[git] -repositories=geany;geany-plugins;infrastructure;newsletter;talks;plugins.geany.org;www.geany.org;geany-themes - -[irc] -channel=#geany -host=localhost -port=7766 - -[shortener] -url=https://geany.org/s/api/create/ -username=username -password=123456-789-123456-789
Modified: scripts/git2irc/git2irc.py 247 lines changed, 0 insertions(+), 247 deletions(-) =================================================================== @@ -1,247 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# git2irc.py - Notify the Geany IRC channel of Git commits -# -# Copyright 2012 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> -# Copyright 2012 Matthew Brush <matt(at)geany(dot)org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. -# - -''' -Sends Git commit notifications to IRC via SweetGeany bot. - -Requires a file ``git2irc.conf`` which contains something like this:: - - [git] - repositories=one;or;more;repos - - [irc] - channel=#thechannel - host=hostname - port=portnum - - [shortener] - url=http://tiny.cc/ - login=apiuser - key=apikey - -Not having any of the sections, options or values will result in a run-time -error. No smart checking is performed. -''' - -from cgi import FieldStorage -from configparser import ConfigParser -from copy import deepcopy -from json import dumps, loads -from urllib.request import Request, urlopen -import logging -import logging.handlers -import socket - - -# hard-coded constants, adjust for environment -CONFIG_FILENAME = '/home/geany/git2irc.conf' -LOG_FILENAME = '/var/log/git2irc.log' -# extend on demand -LOG_EMAIL_ADDRESSES = ['enrico@geany.org'] - -# user-agent to be used for requests to tiny.cc -USER_AGENT = 'git2irc.py - https://raw.github.com/geany/infrastructure/master/scripts/git2irc/git2irc.p...' - -# global and cuts across concerns, assumed to be properly initialized later -logger = None # see init_logging() -config = {'git': {}, 'irc': {}, 'shortener': {}} # see init_config() - - -# ---------------------------------------------------------------------- -def init_config(conf_filename): - """ - Reads the configuration file into a global dictionary. - """ - try: - conf = ConfigParser({ - 'git': {'repositories': ''}, - 'irc': {'channel': '', 'host': '', 'port': 0}, - 'shortener': {'url': '', 'login': '', 'key': ''}}) - conf.read(conf_filename) - config['git']['repositories'] = [ - itm.strip() - for itm - in conf.get('git', 'repositories').split(';') - if itm.strip()] - config['irc']['channel'] = conf.get('irc', 'channel') - config['irc']['host'] = conf.get('irc', 'host') - config['irc']['port'] = int(conf.get('irc', 'port')) - config['shortener']['url'] = conf.get('shortener', 'url') - config['shortener']['username'] = conf.get('shortener', 'username') - config['shortener']['password'] = conf.get('shortener', 'password') - - # copy config and replace password before logging - config_for_logging = deepcopy(config) - config_for_logging['shortener']['password'] = '*******' - logger.debug('Read configuration dict: {}'.format(str(config_for_logging))) - # catch-all: will be for invalid config file/section/option, unknown - # filename, etc - except Exception as e: - logger.warning( - "Exception reading config file '{}': {}".format(conf_filename, str(e)), - exc_info=True) - - -# ---------------------------------------------------------------------- -def init_logging(): - """" - Initializes the logging file for all to use. - """ - global logger # used everywhere - logger = logging.getLogger('git2irc') - logger.setLevel(logging.DEBUG) - file_handler = logging.FileHandler(LOG_FILENAME) - file_handler.setLevel(logging.DEBUG) - formatter = logging.Formatter('%(asctime)s %(name)s: %(levelname)s: %(message)s') - file_handler.setFormatter(formatter) - logger.addHandler(file_handler) - # mail - mail_handler = logging.handlers.SMTPHandler( - 'localhost', - 'git-noreply@geany.org', - LOG_EMAIL_ADDRESSES, - 'Error on git_post_commit') - mail_handler.setLevel(logging.WARNING) - logger.addHandler(mail_handler) - logger.debug('Logging initialized') - - -# ---------------------------------------------------------------------- -def shorten_url(long_url): - """ - Uses the geany.org/s/ API to shorten URL's for nice IRC messages. - """ - request_data = dumps({ - "auth": { - "username": config['shortener']['username'], - "password": config['shortener']['password'] - }, - "url": { - "fullUrl": long_url - } - }) - request_data = request_data.encode('utf-8') - request_url = config['shortener']['url'] - short_url = long_url # default is to return same URL (ie. in case of error) - request = Request(request_url, headers={"User-Agent": USER_AGENT}, data=request_data) - try: - resp_file = urlopen(request) - response = resp_file.read() - resp_dict = loads(response.decode('utf-8')) - if int(resp_dict['statusCode']) == 200: - short_url = resp_dict['url']['shortUrl'] - logger.debug('Shortened URL: {}'.format(short_url)) - else: - logger.warning( - 'Error shortening URL: {}: {}'.format( - resp_dict['statusCode'], - resp_dict['errorMessage'])) - except Exception as exc: # generally, urllib2.URLError - # read JSON response but just give up if there is no JSON in the response - # and log only the raw error - try: - response = exc.read() - reponse_data = loads(response) - logger.warning( - 'Error shortening URL: {}: {}'.format( - reponse_data['statusCode'], - reponse_data['errorMessage'])) - except Exception: - logger.warning('Exception shortening URL: {}'.format(str(exc)), exc_info=True) - - return short_url - - -# ---------------------------------------------------------------------- -def send_commit(message): - """ - Dumps the message to IRC via SweetGeany. - """ - irc_message = 'Freenode {} {}'.format(config['irc']['channel'], message) - irc_bot_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - irc_bot_socket.connect((config['irc']['host'], config['irc']['port'])) - irc_bot_socket.send(irc_message.encode('utf-8')) - irc_bot_socket.close() - logger.debug('Message sent to IRC: {}'.format(message)) - - -# ---------------------------------------------------------------------- -def handle_irc_message(repository, content): - """ - Processes the post-commit-hook from Github.com web hooks. - """ - try: - branch = content['ref'] - branch = branch.rsplit('/', 1)[1] - except (KeyError, IndexError) as rev_parse_e: - logger.warning('An error occurred at ref parsing: {}'.format(rev_parse_e), exc_info=True) - branch = 'unknown' - - for commit in content['commits']: - author = commit['author'].get('username', 'Unknown User') - commit_id = commit['id'] - message = commit['message'].splitlines()[0] - url = shorten_url(commit['url']) - irc_line = '[{}/{}] {} - {} ({})'.format(repository, branch, author, message, url) - send_commit(irc_line) - logger.info( - "Sent message to channel '{}' for '{}' ({})".format( - config['irc']['channel'], - author, - commit_id)) - - -# ---------------------------------------------------------------------- -def main(): - """ - Script entry-point, reads from github.com request and processes the - event. - """ - # parse query string - arguments = FieldStorage(keep_blank_values=True) - - json = arguments.getvalue('payload') - content = loads(json) - if 'commits' in content: - repo = content['repository']['name'] - if repo in config['git']['repositories']: - handle_irc_message(repo, content) - - -# ---------------------------------------------------------------------- -if __name__ == '__main__': - init_logging() - logger.debug('Script started') - init_config(CONFIG_FILENAME) - - try: - main() - except Exception as e: - logger.warning('An error occurred: {}'.format(e), exc_info=True) - - print('Content-type: text/html') - print() - - logger.debug('Script complete') - logging.shutdown()
Modified: scripts/irclog.py 395 lines changed, 0 insertions(+), 395 deletions(-) =================================================================== @@ -1,395 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# IRC Log parser -# -# Copyright 2010 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> -# License: GPLv2 -# - -from os.path import exists -from html.entities import entitydefs -from time import ctime -import datetime -import re -import sys - - -CHANNEL = '#geany' -TITLE = 'IRC Logs for {} @ irc.freenode.net'.format(CHANNEL) - -MSG_TYPE_NORMAL = 1 -MSG_TYPE_STATUS = 2 -MSG_TYPE_ACTION = 3 - - -# 2010-01-31T14:09:29 <eht16> logs and stats are currently broken(i.e. not up2date), ... -# 2010-01-31T14:09:34 <ct|kyle> I did not think that would still work -# 2010-01-31T14:09:45 <ct|kyle> I figured that -# 2010-01-31T14:09:52 <eht16> I wrote a Geany plugin :) -REGEXP_MSG = re.compile(r'^(\d+)-([\d\w]+)-(\d+)[ T](\d+):(\d+):(\d+) <(\S+)> (.*)') - -# 2010-01-31T02:25:40 *** SweetGeany has joined #geany -# 2010-01-31T02:25:48 *** SweetGeany has left #geany -# 2010-01-31T02:26:57 *** SweetGeany has joined #geany -# 2010-01-31T03:25:54 *** _dmaphy_ has joined #geany -# 2010-01-31T03:27:36 *** dmaphy has quit IRC -# 2010-01-31T03:27:43 *** _dmaphy_ is now known as dmaphy -REGEXP_STATUS = re.compile(r'(\d+)-([\d\w]+)-(\d+)[ T](\d+):(\d+):(\d+) *** (\S+) ?(.*)') - -# 2010-01-31T14:17:18 * eht16 just noticed, 'make distcheck' is broken for Geany -REGEXP_ACTION = re.compile(r'(\d+)-([\d\w]+)-(\d+)[ T](\d+):(\d+):(\d+) * (\S+) ?(.*)') - - -HTML_TEMPLATE = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - -<head> - <title>{title}</title> - <meta http-equiv="content-type" content="text/html;charset=utf-8" /> - <meta name="generator" content="Geany 1.25" /> - <link rel='icon' href='/favicon.ico' type='image/x-icon' /> - <link rel='shortcut icon' href='/favicon.ico' /> - <style type="text/css"> - body {{ - font-size: 90%; - }} - h1, h2, h3 {{ - color: #70709f; clear: left; - }} - - .nick1 {{ - color: #00AA33; - }} - .nick2 {{ - color: #AA0000; - }} - .nick3 {{ - color: #005500; - }} - .nick4 {{ - color: #FF0077; - }} - .nick5 {{ - color: blue; - }} - .nick6 {{ - color: #8B008B; - }} - .nick7 {{ - color: #50507f; - }} - .nick8 {{ - color: #00008B; - }} - .nick9 {{ - color: #222222; - }} - - tr, td {{ - vertical-align: top; - }} - - img {{ - border: 0px; - }} - - .status {{ - font-size: 80%; - color: gray; - }} - - .action {{ - font-weight: bold; - }} - - #log {{ - border-collapse: collapse; - width: 100%; - border: 1px solid #efefef; - }} - - #log tr {{ - border-top: 1px solid #efefef; - }} - #log tr.head {{ - border-top-style: none; - }} - #log tr.dark {{ - background-color: #dfdfdf; - }} - - #log td, th {{ - font-family: Consolas, "Lucida Console", "Courier New", monospace; - padding: 0.2em 0.4em; - }} - - #log th {{ - border-bottom: 1px solid #C0C0C0; - }} - - #log .nick {{ - text-align: right; - border-right: 1px solid #C0C0C0; - }} - #log .msg {{ - border-right: 1px solid #efefef; line-height: 1.3em; - }} - #log .time {{ - border-left: 1px solid #efefef; - }} - </style> -</head> - -<body> - <h1>{title}</h1> - - <table id="log" style="clear:both"> - <tr class="head"> - <th>Time</th> - <th>Nick</th> - <th>Message</th> - </tr> - {content} - </table> - <p> </p> - <p>Stats generated by <a href="https://github.com/geany/infrastructure/blob/master/scripts/irclog.py">irclog.py</a> - on {ctime} (times in UTC{date})</p> - <p> - <a href="https://validator.w3.org/check?uri=referer"> - <img src="https://i18n.geany.org/button-xhtml.png" alt="Valid XHTML 1.0 Strict" /> - </a> - - <a href="https://www.geany.org"> - <img src="https://i18n.geany.org/button-geany.png" alt="Geany" /> - </a> - </p> -</body> -</html> -''' - - -class LogEntry: - - # ---------------------------------------------------------------------- - def __init__(self): - self.date = None - self.nick = None - self.msg = None - self.msg_type = MSG_TYPE_NORMAL - - # ---------------------------------------------------------------------- - def __str__(self): - return 'LogEntry: {}: {}: {}'.format(self.date, self.nick, self.msg) - - -######################################################################## -class IrcLogFormatter: - - # ---------------------------------------------------------------------- - def __init__(self, input_filename, output_filename): - self._input_filename = input_filename - self._output_filename = output_filename - self._log_lines = None - self._last_nick_index = 1 - self._entitydefs_inverted = dict() - self._badchars_regex = None - self._been_fixed_regex = None - self._nick_color_index = dict() - self._setup_entity_definitions() - - # ---------------------------------------------------------------------- - def _setup_entity_definitions(self): - for key, value in entitydefs.items(): - value = value - self._entitydefs_inverted[value] = key - - self._badchars_regex = re.compile('|'.join(entitydefs.values())) - self._been_fixed_regex = re.compile(r'&\w+;|&#[0-9]+;') - - # ---------------------------------------------------------------------- - def format(self): - self._get_contents() - content = self._create_table() - if self._output_filename == '-': - date = '' - else: - date = ', will be generated every 24 hours' - - output = HTML_TEMPLATE.format( - title=TITLE, - content=content, - date=date, - ctime=ctime()) - - if self._output_filename == '-': - print(output) - else: - with open(self._output_filename, 'w') as output_file: - output_file.write(output) - - # ---------------------------------------------------------------------- - def _get_contents(self): - self._log_lines = list() - if not exists(self._input_filename): - # the logfile is missing after rotation and before Supybot has flushed the - # current log to disk, so use a dummy log message - entry = LogEntry() - entry.date = datetime.datetime.now() - entry.nick = 'SweetGeany' - entry.msg = 'Nothing has been logged yet' - self._log_lines.append(entry) - return - - with open(self._input_filename) as file_handle: - for line in file_handle: - match = REGEXP_MSG.match(line) - if match and len(match.groups()) == 8: - groups = match.groups() - entry = LogEntry() - entry.date = _create_datetime_from_tuple(groups) - entry.nick = groups[6] - entry.msg = groups[7].strip() - self._log_lines.append(entry) - else: - match = REGEXP_STATUS.match(line) - if match and len(match.groups()) == 8: - groups = match.groups() - entry = LogEntry() - entry.date = _create_datetime_from_tuple(groups) - entry.nick = groups[6] - entry.msg = groups[7] - entry.msg_type = MSG_TYPE_STATUS - self._log_lines.append(entry) - else: - match = REGEXP_ACTION.match(line) - if match and len(match.groups()) == 8: - groups = match.groups() - entry = LogEntry() - entry.date = _create_datetime_from_tuple(groups) - entry.nick = groups[6] - entry.msg = groups[7] - entry.msg_type = MSG_TYPE_ACTION - self._log_lines.append(entry) - else: - print('Failed: {}'.format(line), file=sys.stderr) - - # ---------------------------------------------------------------------- - def _create_table(self): - result = '' - row_index = 0 - last_day = 0 - - for entry in self._log_lines: - if not entry.msg: - continue - - # Date header - if last_day != entry.date.day: - date = entry.date.strftime('%Y-%m-%d') - result += '<tr><th colspan="3">{}</th></tr>'.format(date) - last_day = entry.date.day - - row_index += 1 - if row_index % 2 == 0: - row_alt = ' class="dark"' - else: - row_alt = '' - - if entry.msg_type == MSG_TYPE_STATUS: - row_alt = ' class="status"' - entry.msg = '{} {}'.format(entry.nick, entry.msg) - entry.nick = '' - elif entry.msg_type == MSG_TYPE_ACTION: - row_alt = ' class="action"' - entry.msg = '{} {}'.format(entry.nick, entry.msg) - entry.nick = '' - - result += ''' - <tr{}> - <td class="time">{}</td> - <td class="nick nick{}">{}</td> - <td class="msg">{}</td> - </tr>'''.format( - row_alt, - entry.date.strftime(u'%H:%M'), - self._get_color_index(entry.nick), - self._html_escape(entry.nick), - self._html_escape(entry.msg)) - - return result - - # ---------------------------------------------------------------------- - def _get_color_index(self, nick): - if nick not in self._nick_color_index: - if self._last_nick_index > 9: - self._last_nick_index = 1 - - self._nick_color_index[nick] = self._last_nick_index - self._last_nick_index += 1 - - return self._nick_color_index[nick] - - # ---------------------------------------------------------------------- - def _html_escape(self, text): - if self._been_fixed_regex.findall(text): - return text - - keyholder = dict() - for bad_char in self._badchars_regex.findall(text): - keyholder[bad_char] = 1 - - text = text.replace('&', '&') - text = text.replace('ß', 'ß') - text = text.replace('\x01', ' ') # ASCII char #1, SOH, sent by some clients for ACTIONs - text = text.replace('\x80', '€') - for each in keyholder: - if each == '&': - continue - - better = self._entitydefs_inverted[each] - if not better.startswith('&#'): - better = '&{};'.format(self._entitydefs_inverted[each]) - - text = text.replace(each, better) - return text - - -# ---------------------------------------------------------------------- -def _create_datetime_from_tuple(values): - return datetime.datetime( - int(values[0]), - int(values[1]), - int(values[2]), - int(values[3]), - int(values[4]), - int(values[5])) - - -# ---------------------------------------------------------------------- -def _try_to_decode(value): - try: - return value.encode('utf-8') - except UnicodeError: - try: - return value.encode('latin1') - except UnicodeError: - return repr(value) - - -# ---------------------------------------------------------------------- -def main(): - if len(sys.argv) < 3: - print('Usage: irclog.py <input-file> <output-file>', file=sys.stderr) - exit(1) - - input_filename = sys.argv[1] - output_filename = sys.argv[2] - - irc_log_formatter = IrcLogFormatter(input_filename, output_filename) - irc_log_formatter.format() - - -if __name__ == '__main__': - main()
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).