Branch: refs/heads/add_ci_builders
Author: Enrico Tröger <enrico.troeger(a)uvena.de>
Committer: Enrico Tröger <enrico.troeger(a)uvena.de>
Date: Sun, 29 May 2022 14:35:56 UTC
Commit: f9b6e2d669967978984fa9185f40e9a0ee1508c2
https://github.com/geany/infrastructure/commit/f9b6e2d669967978984fa9185f40…
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(a)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(a)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(a)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.…'
-
-# 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(a)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).
Branch: refs/heads/add_ci_builders
Author: Enrico Tröger <enrico.troeger(a)uvena.de>
Committer: GitHub <noreply(a)github.com>
Date: Sun, 18 Sep 2022 19:29:25 UTC
Commit: a6b52c9afc0b35fa69e9a9422ac1130fc18befc8
https://github.com/geany/infrastructure/commit/a6b52c9afc0b35fa69e9a9422ac1…
Log Message:
-----------
Merge branch 'master' into add_ci_builders
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/git_hooks/geany_commit_utils.py
scripts/git_hooks/github_commit_mail.py
scripts/git_hooks/post_commit_hook.py
scripts/git_hooks/update_repositories.py
scripts/irclog.py
Modified: README.md
20 lines changed, 2 insertions(+), 18 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
@@ -66,16 +60,6 @@ These scripts are used for the nightly builds, for details see
[builders/README.md](builders/README.md).
-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(a)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(a)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(a)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.…'
-
-# 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(a)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/git_hooks/geany_commit_utils.py
45 lines changed, 22 insertions(+), 23 deletions(-)
===================================================================
@@ -3,16 +3,15 @@
# Author: Enrico Tröger
# License: GPLv2
#
+
'''
Utility functions for the Geany GIT hook/mirror scripts
'''
-
-from subprocess import Popen, PIPE
import logging
+from subprocess import PIPE, Popen
-#----------------------------------------------------------------------
def setup_file_logging(name, logfile):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
@@ -25,32 +24,32 @@ def setup_file_logging(name, logfile):
return logger
-#----------------------------------------------------------------------
def run_command(repository_path, command, redirect_stdout=None, run_as=None, logger=None):
if run_as:
command = ('sudo', '-u', run_as) + command
- process = Popen(command, cwd=repository_path, stdout=PIPE, stderr=PIPE)
- stdout, stderr = process.communicate()
- output = u''
- if stdout:
- output = u'%s\nStdout:\n%s' % (output, stdout)
- if redirect_stdout:
- target_file = open(redirect_stdout, 'w')
- target_file.write(stdout)
- target_file.close()
- if stderr:
- output = u'%s\nStderr:\n%s' % (output, stderr)
- if logger:
- exit_code = process.returncode
- logger.debug(u'Command "%s" exited with code %s: %s' % (' '.join(command), exit_code, output))
-
-
-#----------------------------------------------------------------------
+ with Popen(command, cwd=repository_path, stdout=PIPE, stderr=PIPE) as process:
+ stdout, stderr = process.communicate()
+ output = ''
+ if stdout:
+ stdout = stdout.decode('utf-8')
+ output = f'{output}\nStdout:\n{stdout}'
+ if redirect_stdout:
+ with open(redirect_stdout, 'w', encoding='utf-8') as target_file:
+ target_file.write(stdout)
+
+ if stderr:
+ stderr = stderr.decode('utf-8')
+ output = f'{output}\nStderr:\n{stderr}'
+ if logger:
+ exit_code = process.returncode
+ logger.debug('Command "%s" exited with code %s: %s', ' '.join(command), exit_code, output)
+
+
def update_repository(repository, repository_path, logger, run_as=None):
- logger.info(u'Updating repository %s' % repository)
+ logger.info(f'Updating repository {repository}')
run_command(repository_path, ('git', 'remote', 'update'), run_as=run_as, logger=logger)
run_command(repository_path, ('git', 'update-server-info'), run_as=run_as, logger=logger)
run_command(repository_path,
('git', 'log', '--max-count=1', '--format="%cd"', '--date=local'),
- redirect_stdout='%s/_geany/cgit_age' % repository_path,
+ redirect_stdout=f'{repository_path}/_geany/cgit_age',
logger=logger)
Modified: scripts/git_hooks/github_commit_mail.py
116 lines changed, 45 insertions(+), 71 deletions(-)
===================================================================
@@ -8,29 +8,29 @@
Github Post-Receive commit hook
'''
-
-from dateutil import parser as dateutil_parser
+import logging
+import sys
+import urllib.request
+from email import charset
+from email.header import Header
from email.mime.text import MIMEText
-from email.Header import Header
-from email.utils import formatdate, formataddr
+from email.utils import formataddr, formatdate
from json import loads
from smtplib import SMTP
from time import mktime
-import logging
-import sys
-import urllib2
+
+from dateutil import parser as dateutil_parser
+
# Python likes to encode MIME messages with base64, I prefer plain text (#issue12552)
-from email import charset
charset.add_charset('utf-8', charset.SHORTEST)
-
HTTP_REQUEST_TIMEOUT = 30
LOG_LEVEL = logging.DEBUG
-EMAIL_SENDER = u'git-noreply(a)geany.org'
-EMAIL_HOST = u'localhost'
-EMAIL_SUBJECT_TEMPLATE = u'[%(user)s/%(repository)s] %(short_hash)s: %(short_commit_message)s'
-EMAIL_BODY_TEMPLATE = u'''Branch: %(branch)s
+EMAIL_SENDER = 'git-noreply(a)geany.org'
+EMAIL_HOST = 'localhost'
+EMAIL_SUBJECT_TEMPLATE = '[%(user)s/%(repository)s] %(short_hash)s: %(short_commit_message)s'
+EMAIL_BODY_TEMPLATE = '''Branch: %(branch)s
Author: %(author)s
Committer: %(committer)s
Date: %(commit_date_formatted)s
@@ -50,7 +50,7 @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
'''
-EMAIL_DIFF_TEMPLATE = u'''Modified: %(filename)s
+EMAIL_DIFF_TEMPLATE = '''Modified: %(filename)s
%(changes)s lines changed, %(additions)s insertions(+), %(deletions)s deletions(-)
===================================================================
%(patch)s
@@ -75,61 +75,49 @@
}
-########################################################################
-class CommitMailGenerator(object):
- """"""
+class CommitMailGenerator:
- #----------------------------------------------------------------------
def __init__(self, user, repository, branch, commits, logger):
self._user = user
self._repository = repository
self._branch = branch
self._commits = commits
self._logger = logger
- #----------------------------------------------------------------------
def generate_commit_mails(self):
for commit in self._commits:
self._try_to_generate_commit_mail(commit)
- #----------------------------------------------------------------------
def _try_to_generate_commit_mail(self, commit):
try:
self._generate_commit_mail(commit)
- except Exception, e:
- self._logger.error('An error occurred while processing commit %s: %s' %
- (commit, e), exc_info=True)
+ except Exception as exc:
+ self._logger.error('An error occurred while processing commit %s: %s',
+ commit, exc, exc_info=True)
- #----------------------------------------------------------------------
def _generate_commit_mail(self, commit):
full_commit_info = self._query_commit_info(commit)
commit_info = self._adapt_commit_info(full_commit_info)
self._send_mail(commit_info)
- #----------------------------------------------------------------------
def _query_commit_info(self, commit):
- url_parameters = dict(user=self._user,
- repository=self._repository,
- commit=commit)
- url = u'https://api.github.com/repos/%(user)s/%(repository)s/commits/%(commit)s' % \
- url_parameters
- handle = urllib2.urlopen(url, timeout=HTTP_REQUEST_TIMEOUT)
- self._log_rate_limit(handle)
- # parse response
- response_json = handle.read()
- response = loads(response_json)
+ url = f'https://api.github.com/repos/{self._user}/{self._repository}/commits/{commi…'
+
+ with urllib.request.urlopen(url, timeout=HTTP_REQUEST_TIMEOUT) as handle:
+ self._log_rate_limit(handle)
+ # parse response
+ response_json = handle.read()
+ response = loads(response_json)
return response
- #----------------------------------------------------------------------
def _log_rate_limit(self, urllib_handle):
headers = urllib_handle.info()
rate_limit_remaining = headers.get('X-RateLimit-Remaining', '<unknown>')
rate_limit = headers.get('X-RateLimit-Limit', '<unknown>')
length = headers.get('Content-Length', '<unknown>')
- self._logger.debug(u'Github rate limits: %s/%s (%s bytes received)' %
- (rate_limit_remaining, rate_limit, length))
+ self._logger.debug('Github rate limits: %s/%s (%s bytes received)',
+ rate_limit_remaining, rate_limit, length)
- #----------------------------------------------------------------------
def _adapt_commit_info(self, full_commit_info):
branch = self._branch
commit = full_commit_info['sha']
@@ -164,34 +152,27 @@ def _adapt_commit_info(self, full_commit_info):
modified_files_list=modified_files_list,
modified_files_diffs=modified_files_diffs)
- #----------------------------------------------------------------------
def _generate_commit_url(self, commit):
- url_parameters = dict(user=self._user,
- repository=self._repository,
- commit=commit)
- return u'https://github.com/%(user)s/%(repository)s/commit/%(commit)s' % url_parameters
+ return f'https://github.com/{self._user}/{self._repository}/commit/{commit}'
- #----------------------------------------------------------------------
def _get_name(self, full_commit_info, name):
- return u'%s <%s>' % (full_commit_info['commit'][name]['name'],
- full_commit_info['commit'][name]['email'])
+ commit_name = full_commit_info['commit'][name]['name']
+ commit_email = full_commit_info['commit'][name]['email']
+ return f'{commit_name} <{commit_email}>'
- #----------------------------------------------------------------------
def _parse_commit_date(self, date_raw):
return dateutil_parser.parse(date_raw)
- #----------------------------------------------------------------------
def _get_short_commit_message(self, short_commit_message):
return short_commit_message.splitlines()[0]
- #----------------------------------------------------------------------
def _generate_modified_files_list(self, full_commit_info):
modified_files = map(lambda x: x['filename'], full_commit_info['files'])
- return u' %s' % u'\n '.join(modified_files)
+ files_list = '\n '.join(modified_files)
+ return f' {files_list}'
- #----------------------------------------------------------------------
def _generate_modified_files_diffs(self, full_commit_info):
- diffs = u''
+ diffs = ''
for modified_file in full_commit_info['files']:
parameters = dict(filename=modified_file['filename'],
changes=modified_file['changes'],
@@ -202,48 +183,43 @@ def _generate_modified_files_diffs(self, full_commit_info):
# shrink diffs to at most ~ 100KB
if len(diffs) > 100000:
diffs = diffs[:100000]
- diffs += u'@@ Diff output truncated at 100000 characters. @@\n'
+ diffs += '@@ Diff output truncated at 100000 characters. @@\n'
return diffs
- #----------------------------------------------------------------------
def _get_diff_if_available(self, modified_file):
try:
return modified_file['patch']
except KeyError:
- return u'No diff available, check online'
+ return 'No diff available, check online'
- #----------------------------------------------------------------------
def _send_mail(self, commit_info):
author_name = commit_info['author_name'].encode('utf-8')
author_name = str(Header(author_name, 'UTF-8'))
content = EMAIL_BODY_TEMPLATE % commit_info
- msg = MIMEText(content, 'plain', 'utf-8')
+ msg = MIMEText(content.encode('utf-8'), 'plain', 'utf-8')
msg['Subject'] = EMAIL_SUBJECT_TEMPLATE % commit_info
msg['From'] = formataddr((author_name, EMAIL_SENDER))
msg['To'] = self._get_email_recipient()
msg['Date'] = formatdate(commit_info['commit_date'])
smtp_conn = SMTP(EMAIL_HOST)
- smtp_conn.sendmail(EMAIL_SENDER, msg['To'].split(','), msg.as_string())
+ message = msg.as_string()
+ smtp_conn.sendmail(EMAIL_SENDER, msg['To'].split(','), message.encode('utf-8'))
smtp_conn.quit()
- #----------------------------------------------------------------------
def _get_email_recipient(self):
- repository = u'%s/%s' % (self._user, self._repository)
+ repository = f'{self._user}/{self._repository}'
# no error handling on purpose, this should bail out if repository is not in the map
return EMAIL_RECIPIENT_MAP[repository]
-########################################################################
class CommandLineArgumentError(Exception):
- #----------------------------------------------------------------------
def __str__(self):
- return 'Usage: %s <user> <repository> <branch> <commit> ...' % sys.argv[0]
+ return f'Usage: {sys.argv[0]} <user> <repository> <branch> <commit> ...'
-#----------------------------------------------------------------------
def setup_logging():
logging.basicConfig()
logger = logging.getLogger('github_commit_mail_hook')
@@ -252,7 +228,6 @@ def setup_logging():
return logger
-#----------------------------------------------------------------------
def parse_command_line_arguments():
if len(sys.argv) < 5:
raise CommandLineArgumentError()
@@ -265,17 +240,16 @@ def parse_command_line_arguments():
return user, repository, branch, commits
-#----------------------------------------------------------------------
def main():
logger = setup_logging()
try:
user, repository, branch, commits = parse_command_line_arguments()
gen = CommitMailGenerator(user, repository, branch, commits, logger)
gen.generate_commit_mails()
- except CommandLineArgumentError, e:
- print >> sys.stderr, e
- except Exception, e:
- logger.warn(u'An error occurred: %s', unicode(e), exc_info=True)
+ except CommandLineArgumentError as exc:
+ print(exc, file=sys.stderr)
+ except Exception as exc:
+ logger.warning('An error occurred: %s', str(exc), exc_info=True)
logging.shutdown()
Modified: scripts/git_hooks/post_commit_hook.py
57 lines changed, 25 insertions(+), 32 deletions(-)
===================================================================
@@ -12,18 +12,17 @@
- send a commit mail to the mailing list
'''
-
+import logging
+import logging.handlers
from cgi import FieldStorage
-from geany_commit_utils import setup_file_logging, update_repository
from json import loads
from os import unlink
from os.path import exists
-import github_commit_mail
-import logging
-import logging.handlers
+import github_commit_mail
+from geany_commit_utils import setup_file_logging, update_repository
-LOG_FILENAME = u'/var/log/git_mirror.log'
+LOG_FILENAME = '/var/log/git_mirror.log'
VALID_UPDATE_REPOSITORIES = (
'geany',
'geany-plugins',
@@ -34,29 +33,27 @@
'geany-osx',
'talks',
'geany-themes')
-REPOSITORY_BASE_PATH = u'/srv/www/git.geany.org/repos/%s.git'
-UPDATE_LOCK_FILE = u'%s/_geany/.update_lock'
-UPDATE_NOTIFY_FILE = u'%s/_geany/.update_required'
+REPOSITORY_BASE_PATH = '/srv/www/git.geany.org/repos/%s.git'
+UPDATE_LOCK_FILE = '%s/_geany/.update_lock'
+UPDATE_NOTIFY_FILE = '%s/_geany/.update_required'
# extend on demand
LOG_EMAIL_ADDRESSES = ['enrico(a)geany.org']
-#----------------------------------------------------------------------
def setup_logging():
- logger = setup_file_logging('post_commit_hook', LOG_FILENAME)
+ logger_ = setup_file_logging('post_commit_hook', LOG_FILENAME)
# mail
mail_handler = logging.handlers.SMTPHandler(
- u'localhost',
- u'git-noreply(a)geany.org',
+ 'localhost',
+ 'git-noreply(a)geany.org',
LOG_EMAIL_ADDRESSES,
- u'Error on git_post_commit')
+ 'Error on git_post_commit')
mail_handler.setLevel(logging.WARNING)
- logger.addHandler(mail_handler)
+ logger_.addHandler(mail_handler)
- return logger
+ return logger_
-#----------------------------------------------------------------------
def handle_repository_update(repository):
repository_path = REPOSITORY_BASE_PATH % repository
lock_file_path = UPDATE_LOCK_FILE % repository_path
@@ -65,19 +62,16 @@ def handle_repository_update(repository):
# if there is currently an update process running, simply mark the repository to be updated
# again later, a cronjob will pick it
update_notify_path = UPDATE_NOTIFY_FILE % repository_path
- update_notify = open(update_notify_path, 'w')
- update_notify.write('1')
- update_notify.close()
- logger.warn(u'Not updating repository %s because it is locked, leaving a notify', repository)
+ with open(update_notify_path, 'w', encoding='utf-8') as update_notify:
+ update_notify.write('1')
+
+ logger.warning('Not updating repository %s because it is locked, leaving a notify', repository)
else:
- lock_file = open(lock_file_path, 'w')
- update_repository(repository, repository_path, logger)
- # remove lockfile
- lock_file.close()
- unlink(lock_file_path)
+ with open(lock_file_path, 'w', encoding='utf-8'):
+ update_repository(repository, repository_path, logger)
+ unlink(lock_file_path)
-#----------------------------------------------------------------------
def process_commit_mails(content):
user = content['repository']['owner']['name']
repository = content['repository']['name']
@@ -90,7 +84,6 @@ def process_commit_mails(content):
generator.generate_commit_mails()
-#----------------------------------------------------------------------
def main():
# parse query string
arguments = FieldStorage(keep_blank_values=True)
@@ -109,12 +102,12 @@ def main():
logger = setup_logging()
try:
main()
-except Exception, e:
- logger.warn(u'An error occurred: %s', unicode(e), exc_info=True)
+except Exception as exc:
+ logger.warning('An error occurred: %s', str(exc), exc_info=True)
-print 'Content-type: text/html'
-print
+print('Content-type: text/html')
+print()
logging.shutdown()
Modified: scripts/git_hooks/update_repositories.py
44 lines changed, 19 insertions(+), 25 deletions(-)
===================================================================
@@ -12,31 +12,29 @@
post_commit_hook script to be out-of-date.
'''
-from geany_commit_utils import setup_file_logging, update_repository
+import logging
from os import listdir, unlink
from os.path import exists, join
-import logging
+from geany_commit_utils import setup_file_logging, update_repository
-LOG_FILENAME = u'/var/log/git_mirror.log'
-REPOSITORY_BASE_PATH = u'/srv/www/git.geany.org/repos/'
-UPDATE_LOCK_FILE = u'%s/_geany/.update_lock'
-UPDATE_NOTIFY_FILE = u'%s/_geany/.update_required'
+LOG_FILENAME = '/var/log/git_mirror.log'
+REPOSITORY_BASE_PATH = '/srv/www/git.geany.org/repos/'
+UPDATE_LOCK_FILE = '%s/_geany/.update_lock'
+UPDATE_NOTIFY_FILE = '%s/_geany/.update_required'
-#----------------------------------------------------------------------
def setup_logging():
- logger = setup_file_logging('update_repositories', LOG_FILENAME)
+ logger_ = setup_file_logging('update_repositories', LOG_FILENAME)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(name)s: %(levelname)s: %(message)s')
handler.setFormatter(formatter)
- logger.addHandler(handler)
+ logger_.addHandler(handler)
- return logger
+ return logger_
-#----------------------------------------------------------------------
def handle_repository_update(repository):
repository_path = join(REPOSITORY_BASE_PATH, repository)
lock_file_path = UPDATE_LOCK_FILE % repository_path
@@ -46,20 +44,16 @@ def handle_repository_update(repository):
return
if exists(update_notify_path):
- update_notify_file = open(update_notify_path, 'r+')
- need_update = update_notify_file.read() == '1'
- if need_update:
- lock_file = open(lock_file_path, 'w')
- update_repository(repository, repository_path, logger, run_as='www-data')
- # remove lockfile
- lock_file.close()
- unlink(lock_file_path)
- # unmark update notify
- update_notify_file.truncate(0)
- update_notify_file.close()
+ with open(update_notify_path, 'r+', encoding='utf-8') as update_notify_file:
+ need_update = update_notify_file.read() == '1'
+ if need_update:
+ with open(lock_file_path, 'w', encoding='utf-8'):
+ update_repository(repository, repository_path, logger, run_as='www-data')
+ unlink(lock_file_path)
+ # unmark update notify
+ update_notify_file.truncate(0)
-#----------------------------------------------------------------------
def main():
repositories = listdir(REPOSITORY_BASE_PATH)
for repository in repositories:
@@ -70,6 +64,6 @@ def main():
logger = setup_logging()
try:
main()
- except Exception, e:
- logger.warn(u'An error occurred: %s', unicode(e), exc_info=True)
+ except Exception as exc:
+ logger.warning('An error occurred: %s', str(exc), exc_info=True)
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).