Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

From JRo's implementation #2

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
63633d4
GumBot.git
GumballCrash Sep 30, 2013
cdcf5ab
Extracted some of the more personal settings in skype2irc.py to a con…
irisfofs Oct 1, 2013
3b3d6d9
Added basic vhost support (will tell HostServ to activate vhost if se…
irisfofs Oct 1, 2013
351b2dd
Updated README
irisfofs Oct 1, 2013
410cedb
Update skype2irc.py
crystalllized Oct 2, 2013
a66e54b
Update README.md
crystalllized Oct 2, 2013
143923b
Shows display name rather than handle.
Oct 3, 2013
62abacd
Merge pull request #1 from crystalllized/master
GumballCrash Oct 3, 2013
cb4e131
Bot now ignores unicode characters, instead of throwing an error.
Oct 7, 2013
ae0bb20
Merge pull request #2 from JRoTheGeek/master
irisfofs Oct 10, 2013
79489d6
Merge pull request #2 from JRoTheGeek/master
GumballCrash Oct 21, 2013
1a6c87a
Fixed bug where IRCCloud's 'channel staff' pseduo-channels (ex. \!\@\…
irisfofs Oct 30, 2013
1feedff
Fixed duplicate actions after bot has reconnected
zebranky Nov 14, 2013
2d8d1e5
Added module support; a few minor fixes/tweaks
Nov 25, 2013
9078226
Quotes module fixes and whitelist; config moved to .py
zebranky Nov 26, 2013
9bbdcaa
FUCK CHARACTER ENCODINGS. Also fixed some derpiness.
zebranky Nov 26, 2013
71b81fb
Removed "topics" display; fixed crash on /msg'd actions
Jan 30, 2014
3219062
added karma module (with contributions from Sheva)
Jan 30, 2014
33ccfbe
Added message scanner module.
Feb 2, 2014
7b08d03
Renamed message_scanner.py to something more sensible (auto_reply.py).
Feb 2, 2014
9bca035
Delete message_scanner.py
shirgoldbird Feb 2, 2014
7dc2a24
Merge pull request #10 from ShevaDas/master
GumballCrash Feb 5, 2014
af4b6b7
fixed crashbug upon receiving a line containing only spaces on IRC
Feb 11, 2014
ceab8e4
Merge branch 'master' of github.com:GumballCrash/GumBot
Feb 11, 2014
a665e9b
Print exception when a module fails to load; add utility scripts; min…
zebranky Apr 5, 2014
f38a4a6
Now with 50% less silliness.
Apr 6, 2014
484f8c1
Fixed SQLite threading error in karma
zebranky May 3, 2014
8774257
Changed config.py to config.py.default to not conflict with users' ow…
irisfofs May 29, 2014
507acfe
Strip mIRC color codes from messages
irisfofs Jan 3, 2016
5564323
Removed trailing spaces
irisfofs Jan 3, 2016
4a883e7
Fix stripping color codes to be on decode
irisfofs Jan 3, 2016
457871c
Fix bug with too-greedy stripping regexp
irisfofs Jan 3, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,23 @@ INSTALL

On Ubuntu/Debian you need `python-irclib` and `python-skype` as well as Skype itself to run the script.

This bot runs with `python-irclib` 0.4.8. Newer versions may not have the necessary modules.

For `python-skype` I used the version 1.0.31.0 provided at `ppa:skype-wrapper/ppa`. Although newer version is packaged even for Ubuntu 11.04, this package didn't work out of the box on Ubuntu 12.04.

Module deps:
* quotes and addquote require python-requests

CONFIGURE
---------

You can configure the IRC servers and Skype chatrooms to mirror in the header of `skype2irc.py`. You may define one IRC server and as many pairs of IRC channels and Skype chatrooms as you like. Skype chatrooms are defined by the blob, which you can obtain writing `/get uri` in a chatroom.
You can configure the IRC servers and Skype chatrooms to mirror in the configuration file `config.json`. You may define one IRC network (optionally with multiple servers) and as many pairs of IRC channels and Skype chatrooms as you like. Skype chatrooms are defined by the blob, which you can obtain writing `/get uri` in a chatroom.

You may need to join your Skype chatroom to be mirrored before actually starting the gateway, because it seems that Skype API isn't always able to successfully join the chatroom using a blob provided (I usually get a timeout error). So make sure you have an access to chatroom using GUI before starting to hassle with the code.

The default values provided in the header of `skype2irc.py` should be enough to give the program a test run.
The default values provided should be enough to give the program a test run.

If you want to use an option to save broadcast states for IRC users, working directory for the script has to be writable.
If you want to use an option to save broadcast states for IRC users, the working directory for the script has to be writable.

RUN
---
Expand All @@ -40,3 +45,5 @@ To run the gateway, Skype must be running and you must be logged in. You can do
You can run `skype2irc.py` just from command line or use `ircbot.sh` to loop it. You can also run it from plain terminal providing the X desktop Skype will be started like `DISPLAY="host:0.0" ./skype2irc.py`.

It could also make sense to run it using `ssh -X user@host` session or with something similar.

On Mac OS X, ensure the bot is being run in 32-bit Python. 64-bit Python will result in segfaults.
35 changes: 35 additions & 0 deletions auto_reply.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#Bot will auto-respond to lines containing a specified regex
#I <3 PR

import re

config = None
usemap = None
ircbot = None

#put the regex you want here
my_exp = re.compile('')

#put the message to auto-respond with here
#suggestion: "Just ignore her."
my_response = ''

def message_scan(source, msg):
msg = msg.strip()
ismatch = my_exp.match(msg)
if ismatch:
return source + ": " + my_response

def irc_msg(source, target, msg):
if not target in config['channels']:
return
scanner = message_scan(source, msg)
if scanner and target in config['channels']:
ircbot.say(target, scanner)
usemap[target].SendMessage(scanner)

def skype_msg(sourceDisplay, sourceHandle, target, msg):
scanner = message_scan(sourceDisplay, msg)
if scanner and usemap[target] in config['channels']:
ircbot.say(usemap[target], scanner)
target.SendMessage(scanner)
16 changes: 16 additions & 0 deletions config.py.default
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# GumBot config file

config = {
"servers": [("127.0.0.1", 6667)],
"nick": "GumBot",
"botname": "IRC <-> Skype Bot",
"password": "",
"vhost": False,
"mirrors": {
"#example": "blob"
},
"modules": {
# "example": {},
# "quotes": {"url": "", "http-user": "", "http-pass": "", "channels": ["#example"]},
}
}
13 changes: 13 additions & 0 deletions example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# example GumBot module

config = None
usemap = None
ircbot = None

def irc_msg(source, target, msg):
usemap[target].SendMessage('EXAMPLE: IRC msg %s -> %s: %s' % (source, target, msg))
print 'EXAMPLE: IRC msg %s -> %s: %s' % (source, target, msg)

def skype_msg(sourceDisplay, sourceHandle, target, msg):
ircbot.say(usemap[target], 'EXAMPLE: Skype msg %s (%s) -> %s: %s' % (sourceHandle, sourceDisplay, target, msg))
print 'EXAMPLE: Skype msg %s (%s) -> %s: %s' % (sourceHandle, sourceDisplay, target, msg)
Empty file modified ircbot.sh
100755 → 100644
Empty file.
3 changes: 3 additions & 0 deletions ircbot_once.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

DISPLAY="host:0.0" python skype2irc.py
123 changes: 123 additions & 0 deletions karma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import re
import sqlite3
import datetime

with sqlite3.connect('karma.db') as conn:
cur = conn.cursor()
try:
cur.execute('''CREATE TABLE "karma" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL COLLATE NOCASE,
"delta" INTEGER,
"comment" TEXT,
"add_time" TEXT NOT NULL
);''')
conn.commit()
except sqlite3.OperationalError:
pass

config = None
usemap = None
ircbot = None

exp = re.compile("^(\([^)]+\)|[^ ]+)([+]{2}|[-]{2})(.*)$")

def getsubject(msg):
msg = msg.strip().lower()
if msg[0] == '(' and msg[len(msg) - 1] == ')':
msg = msg[0:len(msg)-1].strip()
return msg

def getreason(msg, sender):
msg = msg.strip()
if msg.startswith('#'):
return msg[1:].strip()
elif msg.startswith('//'):
return msg[2:].strip()
else:
return ''

def fetch_karma(ktgt):
with sqlite3.connect('karma.db') as conn:
cur = conn.cursor()
cur.execute('''SELECT SUM(`delta`) FROM karma WHERE `name` LIKE ?;''', (ktgt,))
ksum = cur.fetchone()[0]
return ksum

def karmaparse(source, msg):
msg = msg.strip()
ismatch = exp.match(msg)
if ismatch:
subject = getsubject(ismatch.group(1))
amount = ismatch.group(2)
if amount == '--':
amount = -1
ktype = 'negative'
else:
amount = 1
ktype = 'positive'
reason = getreason(ismatch.group(3), source)
if reason:
reason = ' for "%s"' % reason
if subject == source.lower() and amount > 0:
return "You can't give karma to yourself... loser."
else:
with sqlite3.connect('karma.db') as conn:
cur = conn.cursor()
cur.execute('''INSERT INTO karma (`name`,`delta`,`comment`,`add_time`) VALUES (?,?,?,?)''', (subject, amount, reason, datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')))
conn.commit()
if subject == config['nick'].lower() and amount > 0:
return "Karma for %s is now %s. Thanks, %s!" % (subject, fetch_karma(subject), source)
elif subject == config['nick'].lower() and amount < 0:
return "Karma for %s is now %s. Pfft." % (subject, fetch_karma(subject))
else:
return "Karma for %s is now %s." % (subject, fetch_karma(subject))
else:
return None

def get_karma(msg):
m = re.match('!karma (.+)', msg)
if not m:
return
ktgt = m.group(1).strip()
ksum = fetch_karma(ktgt)
if ksum is None:
kstr = 'No karma has ever been assigned to %s.' % ktgt
else:
kstr = '%s has %s karma.' % (ktgt, ksum)
return kstr


"""
def explain(msg):
m = re.match('!explain (.+)', msg)
if not m:
return
ktgt = m.group(1).strip()
cur.execute('''SELECT comment FROM karma where `name` LIKE ?;''', (ktgt,))
"""


def irc_msg(source, target, msg):
if not target in config['channels']:
return
if msg.startswith('!karma'):
kstr = get_karma(msg)
ircbot.say(target, kstr)
usemap[target].SendMessage(kstr)
else:
karma = karmaparse(source, msg)
if karma and target in config['channels']:
ircbot.say(target, karma)
usemap[target].SendMessage(karma)

def skype_msg(sourceDisplay, sourceHandle, target, msg):
if msg.startswith('!karma'):
kstr = get_karma(msg)
ircbot.say(usemap[target], kstr)
target.SendMessage(kstr)
else:
karma = karmaparse(sourceDisplay, msg)
if karma and usemap[target] in config['channels']:
ircbot.say(usemap[target], karma)
target.SendMessage(karma)
3 changes: 3 additions & 0 deletions killbot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

kill `ps aux | grep skype2irc | grep -v grep | awk '{print $2;}'`
76 changes: 76 additions & 0 deletions quotes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# GumBot quotes module
# requires config keys:
# - url
# - http-user
# - http-pass

import requests
import re
import traceback

def encode_utf8_to_iso88591(utf8_text):
# Borrowed from http://jamesmurty.com/2011/12/30/python-code-utf8-to-latin1/
"""
Encode and return the given UTF-8 text as ISO-8859-1 (latin1) with
unsupported characters replaced by '?', except for common special
characters like smart quotes and symbols that we handle as well as we
can.
For example, the copyright symbol => '(c)' etc.

If the given value is not a string it is returned unchanged.

References:

en.wikipedia.org/wiki/Quotation_mark_glyphs#Quotation_marks_in_Unicode
en.wikipedia.org/wiki/Copyright_symbol
en.wikipedia.org/wiki/Registered_trademark_symbol
en.wikipedia.org/wiki/Sound_recording_copyright_symbol
en.wikipedia.org/wiki/Service_mark_symbol
en.wikipedia.org/wiki/Trademark_symbol
"""
if not isinstance(utf8_text, basestring):
return utf8_text
# Replace "smart" and other single-quote like things
utf8_text = re.sub(
u'[\u02bc\u2018\u2019\u201a\u201b\u2039\u203a\u300c\u300d\x91\x92]',
"'", utf8_text)
# Replace "smart" and other double-quote like things
utf8_text = re.sub(
u'[\u00ab\u00bb\u201c\u201d\u201e\u201f\u300e\u300f\x93\x94]',
'"', utf8_text)
# Replace copyright symbol
utf8_text = re.sub(u'[\u00a9\u24b8\u24d2]', '(c)', utf8_text)
# Replace registered trademark symbol
utf8_text = re.sub(u'[\u00ae\u24c7]', '(r)', utf8_text)
# Replace sound recording copyright symbol
utf8_text = re.sub(u'[\u2117\u24c5\u24df]', '(p)', utf8_text)
# Replace service mark symbol
utf8_text = re.sub(u'[\u2120]', '(sm)', utf8_text)
# Replace trademark symbol
utf8_text = re.sub(u'[\u2122]', '(tm)', utf8_text)
# Replace/clobber any remaining UTF-8 characters that aren't in ISO-8859-1
return utf8_text.encode('ISO-8859-1', 'replace')

def get_quote():
try:
r = requests.get(config['url'], auth=(config['http-user'], config['http-pass']), timeout=3)
if r.status_code != 200:
raise Exception()
# FUCK CHARACTER ENCODINGS.
quote = encode_utf8_to_iso88591(r.content.decode('ISO-8859-1'))
return quote
except Exception, e:
traceback.print_exc()
return 'error getting quote :( (%s)' % e

def irc_msg(source, target, msg):
if msg == '!quote' and target in config['channels']:
quote = get_quote()
ircbot.say(target, quote)
usemap[target].SendMessage(quote)

def skype_msg(sourceDisplay, sourceHandle, target, msg):
if msg == '!quote' and usemap[target] in config['channels']:
quote = get_quote()
ircbot.say(usemap[target], quote)
target.SendMessage(quote)
Loading