219 Parser.py

Large diffs are not rendered by default.

@@ -1,5 +1,5 @@
#!/usr/bin/python2
import random
#!/usr/bin/env python
from random import randint, choice

try:
with open("Plugins/AslPlaces.txt", "r") as _f:
@@ -15,10 +15,10 @@
'Virgin Islands', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming']

def asl(msg, sock, users, allowed):
sock.say(msg[3], "{0}/{1}/{2}".format(random.randint(1,80), random.choice(['m','f','trans']), random.choice(locations)))
sock.say(msg[3], "{0}/{1}/{2}".format(randint(1,80), choice(['m','f','trans']), choice(locations)))

hooks = {
'(?:\s+?|^)asl(?:\s+?|$)': [asl, 5, False],
'(?:\s+?|^)asl(?:\s+?|$)': [asl, 5, False],
}

helpstring = "Uses a regex to find \"asl\" in a message, sends a \"random\" asl."
@@ -0,0 +1,32 @@
#!/usr/bin/env python
from threading import Timer
'''
I decided that I needed some sort of 'control' over Wherg's commands.
So here it is. This 'module' was taken out of Plinko.py itself and placed here.
Usage is simple; Just init a Locker class and call Lock(). Check if the
locker is locked before actually doing anything ofc.
IE:
Locker = Locker(5)
if Locker.Locked:
return None
else:
Do_Something()
Locker.Lock()
'''
class Locker(object):
def __init__(self, Time=None):
self.Time = Time if Time and type(Time) == int else 5
# banhammer would be proud ;-;
self.Locked = False

def Lock(self):
if not self.Locked:
self.Locked = True
t = Timer(self.Time, self.Unlock, ())
t.daemon = True
t.start()

def Unlock(self):
self.Locked = False
@@ -1,4 +1,7 @@
#!/usr/bin/python2
#!/usr/bin/env python
from CommandLock import Locker
Lock = Locker(5)

class wordnikObj(object):
def __init__(self, apiFile):
try:
@@ -7,7 +10,7 @@ def __init__(self, apiFile):
except ImportError:
print("* [Dictionary] Could not import wordnik, please read the README and install it.")
self._imported = False

try:
with open(apiFile, "r") as _f:
api = _f.read().strip()
@@ -17,32 +20,37 @@ def __init__(self, apiFile):

if self._imported:
self.Word = Wordnik(api_key=api)

def reply(self, msg, sock, users, allowed):
if self._imported:
if Lock.Locked:
sock.notice(msg[0], "Please wait a little longer before using this command again.")
return None
w = " ".join(msg[4].split()[1:])
defs = []
deflist = self.Word.word_get_definitions(w)[0:3]
numdefs = len(deflist)
for x in deflist:
defs.append(x['text'])

if numdefs == 0:
sock.send("PRIVMSG {0} :\x02[WordNik]\x02 I didn't find any definitions for '{1}'.".format(msg[3], w))
sock.say(msg[3],"\x02[WordNik]\x02 I didn't find any definitions for '{0}'.".format(w))
elif numdefs == 1:
sock.send("PRIVMSG {0} :\x02[WordNik]\x02 I found one definition for '{1}'.".format(msg[3], w))
sock.send("PRIVMSG {0} :\x02[WordNik]\x02 {1}: {2}".format(msg[3], w, defs[0]))
sock.say(msg[3], "\x02[WordNik]\x02 I found one definition for '{0}'.".format(w))
sock.say(msg[3], "\x02[WordNik]\x02 {0}: {1}".format(w, defs[0]))
else:
sock.send("PRIVMSG {0} :\x02[WordNik]\x02 I found {1} definitions for '{2}'.".format(msg[3], numdefs, w))
sock.say(msg[3], "\x02[WordNik]\x02 I found {0} definitions for '{1}'.".format(numdefs, w))
while len(defs) != 0:
sock.send("PRIVMSG {0} :\x02[WordNik]\x02 {1}: {2}".format(msg[3], w, defs.pop(0)))
sock.say(msg[3], "\x02[WordNik]\x02 {0}: {1}".format(w, defs.pop(0)))
Lock.Lock()
else:
sock.say(msg[3], "Please install the python wordnik API and get a developers API key. http://developer.wordnik.com/libraries#python")
sock.say(msg[3], "Please tell {0} to install the python wordnik API and get a developers API key. http://developer.wordnik.com/libraries#python".format(allowed.Owner[0]))

W = wordnikObj("Plugins/DictionaryAPIKey.txt")

hooks = {
'^@def': [W.reply, 5, False],
'^@def': [W.reply, 5, False],
}

helpstring = """Polls the WordNik API for a word."""
helpstring = """Polls the WordNik API for a word.
@def <word> - Searches for a word. Case sensitive."""
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python

def _Exec(Message, Sock, Users, Allowed):
x = " ".join(Message[4].split()[1:])
@@ -1,6 +1,8 @@
#!/usr/bin/python2
#!/usr/bin/env python

from random import choice
from CommandLock import Locker
Lock = Locker()

faps = [
"seisatsu.png",
@@ -98,10 +100,13 @@
]

def Fapget(Msg, Sock, Users, Allowed):
Sock.say(Msg[3], "\x02{0}\x02 has to fap to \x02{1}\x02!".format(Msg[0], choice(faps)))

if not Lock.Locked:
Sock.say(Msg[3], "\x02{0}\x02 has to fap to \x02{1}\x02!".format(Msg[0], choice(faps)))
Lock.Lock()
else:
Sock.notice(Msg[0], "Please wait a little longer before using this command again.")
hooks = {
"^@fapget" : [Fapget, 5, False]
}

helpstring = """Returns a random philia/etc for one to fap to."""
helpstring = """@fapget - Returns a random philia/etc for one to fap to."""
@@ -1,6 +1,8 @@
#!/usr/bin/python2
import requests
import re
#!/usr/bin/env python
import requests, re

from CommandLock import Locker
Lock = Locker(5)

def get_fml():
fml_db = []
@@ -30,12 +32,16 @@ def fml():
FmlGen = fml()
def FMLString(msg, sock, users, allowed):
try:
sock.say(msg[3], next(FmlGen))
if not Lock.Locked:
sock.say(msg[3], next(FmlGen))
Lock.Lock()
else:
sock.notice(msg[0], "Please wait a little longer before using this command again.")
except Exception, e:
print("* [FML] Error:\n* [FML] {0}".format(str(e)))

hooks = {
'^@fml': [FMLString, 5, False],
}

helpstring = """Polls FML's from fmylife.com/random"""
helpstring = """@fml - Polls FML's from fmylife.com/random"""
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python

from random import randint
import shelve
@@ -21,9 +21,9 @@ class GuessingStats(object):
totalWins = Number of total wins across all games.
totalPlayers = Number of everyone who has ever played, by nick.
#len(db['Players'])
#The most people who have played at once
A function that gets absolute totals of all players' stats.
{
'Players': {
'Ferus': {
@@ -34,15 +34,15 @@ class GuessingStats(object):
'notValid':0,
'overMax':0, },
#End Players Block },
#Globals
'totalWins':0,
'totalPlayers':len(db['Players'])
{'totalWins':0,}
{'totalPlayers':len(db['Players'])}
}
#Etc
'''
def __init__(self, _StatsDB=None):

def __init__(self, _StatsDB=None):
if _StatsDB:
self._StatsDB = _StatsDB
else:
@@ -54,14 +54,14 @@ def __init__(self, _StatsDB=None):

if 'Players' not in self.StatsDB.keys():
self.StatsDB['Players'] = {}

def Load(self, _db):
x = {}
for key in _db.keys():
x[key] = _db[key]
print("* [Guess] Loaded stats database.")
return x

def Save(self):
try:
_db = shelve.open(self._StatsDB)
@@ -73,7 +73,7 @@ def Save(self):
except Exception, e:
print(repr(e))
return False

def AddStats(self, Player=None, Stat=None, Value=None):
'''
Check if we are adding stats to a player.
@@ -90,7 +90,7 @@ def AddStats(self, Player=None, Stat=None, Value=None):
'tooLow':0,
'wins':0,
}

self.StatsDB['Players'][Player][Stat] += Value

else:
@@ -102,13 +102,35 @@ def AddStats(self, Player=None, Stat=None, Value=None):
except:
print("* [Guess] Error'd")

def GetStats(self, Person):
def GetStatsPlayer(self, Person):
st = self.StatsDB['Players'][Person]

x = "\x02[Guess]\x02 Stats for {0}: {1} Non-valid number(s), {2} Guess(es) over max, {3} Guess(es) under min, {4} Guess(es) too high, {5} Guess(es) too low, and {6} win(s)."
x = x.format(Person, st['notValid'], st['overMax'], st['underMin'], st['tooHigh'], st['tooLow'], st['wins'])
return x

return x

def GetStatsGlobal(self):
p = [[None, 0]]
for player in self.StatsDB['Players']:
if self.StatsDB['Players'][player]['wins'] > p[0][1]:
p[0][0] = player
p[0][1] = self.StatsDB['Players'][player]['wins']
del p[1:]
elif self.StatsDB['Players'][player]['wins'] == p[0][1]:
p.append([player, self.StatsDB['Players'][player]['wins']])
else:
pass

if len(p) == 1:
x = "\x02[Guess]\x02 There have been {0} global win{1}, among {2} total players, with {3} having the most wins of {4}."
x = x.format(self.StatsDB['GlobalWins'], 's' if len(self.StatsDB['GlobalWins']) > 1 or self.StatsDB['GlobalWins'] == 0 else '', \
len(self.StatsDB['Players']), p[0], p[1])
else:
x = "\x02[Guess]\x02 There have been {0} global win{1}, among {2} total players, with the players {3} tied at {4} wins."
x = x.format(self.StatsDB['GlobalWins'], 's' if len(self.StatsDB['GlobalWins']) > 1 or self.StatsDB['GlobalWins'] == 0 else '', \
len(self.StatsDB['Players']), ", ".join(x[0] for x in p), p[0][1])
return x

class GuessingGame(object):
def __init__(self, _stats=False):
self.MaxNum = 250
@@ -132,7 +154,7 @@ def SetMaxNum(self, msg, sock, users, allowed):
self.GenNumber(sock=sock, location=msg[3])
except:
sock.say(msg[3], "I'm sorry {0}, but {1} doesn't seem to be a valid number.".format(msg[0], msg[4].split()[1]))

def CheckGuess(self, msg, sock, users, allowed):
try:
UserGuess = int(msg[4].split()[1])
@@ -146,48 +168,60 @@ def CheckGuess(self, msg, sock, users, allowed):
sock.say(msg[3], "I'm sorry {0}, but my maximum number is set to {1}.".format(msg[0], self.MaxNum))
if self._stats:
self.Stats.AddStats(Player=msg[0], Stat='overMax', Value=1)

elif UserGuess <= 0:
sock.say(msg[3], "I'm sorry {0}, but my number cannot be lower than 0.".format(msg[0]))
if self._stats:
self.Stats.AddStats(Player=msg[0], Stat='underMin', Value=1)

elif UserGuess > self.CurrentNumber:
sock.say(msg[3], "I'm sorry {0}, but my number is lower than that.".format(msg[0]))
if self._stats:
self.Stats.AddStats(Player=msg[0], Stat='tooHigh', Value=1)

elif UserGuess < self.CurrentNumber:
sock.say(msg[3], "I'm sorry {0}, but my number is higher than that.".format(msg[0]))
if self._stats:
self.Stats.AddStats(Player=msg[0], Stat='tooLow', Value=1)

elif UserGuess == self.CurrentNumber:
sock.say(msg[3], "Congratulations {0}, You guessed my number!".format(msg[0]))
self.GenNumber(sock=sock, location=msg[3])
if self._stats:
self.Stats.AddStats(Player=msg[0], Stat='wins', Value=1)
self.Stats.AddStats(Stat='GlobalWins', Value=1)
else:
pass #Wut.

def GetStat(self, msg, sock, users, allowed):
if self._stats:
if msg[4].split()[1]:
x = msg[4].split()[1]
try:
sock.say(msg[3], self.Stats.GetStats(msg[0]))
sock.say(msg[3], self.Stats.GetStatsPlayer(x if x else msg[3]))
except:
sock.say(msg[3], "I'm sorry {0}, but I couldn't find any stats for you.".format(msg[0]))
sock.say(msg[3], "I'm sorry {0}, but I couldn't find anything for '{1}'".format(msg[0], x if x else msg[0]))
else:
sock.say(msg[3], "Stats are not enabled.")

def GetGlobalStat(self, msg, sock, users, allowed):
if self._stats:
sock.say(msg[3], self.Stats.GetStatsGlobal())
else:
sock.say(msg[3], "Stats are not enabled.")

G = GuessingGame(_stats=True)

hooks = {
'^@guess': [G.CheckGuess, 5, False],
'^@setguess': [G.SetMaxNum, 3, False],
'^@checkstats': [G.GetStat, 5, False],
'^@globalstats':[G.GetGlobalStat, 5, False],
}

helpstring = """Provides a nice guessing game. Also saves stats.
@guess #: Allows one to guess the number.
@setguess: Changes the max number.
@checkstats: Checks a users stats."""
@checkstats: Checks a users stats.
@globalstats: Checks global stats.
"""

This file was deleted.

@@ -1,8 +1,10 @@
#!/usr/bin/python2
#!/usr/bin/env python
# InsultGenerator.py - Pulls an 'insult' from http://www.insultgenerator.org/

import requests
from htmldecode import convert
from CommandLock import Locker
Locker = Locker(5)

def insult():
html = requests.get("http://www.insultgenerator.org/")
@@ -11,14 +13,19 @@ def insult():
html = convert(html.content)
insult = html.split("<TR align=center><TD>")[1].split("</TD></TR>")[0]
return insult

def gen(msg, sock, users, allowed):
'''Insult a fgt. :)'''
_insult = "{0}, {1}".format(" ".join(msg[4].split()[1:]), insult())
sock.say(msg[3], _insult)

if not Locker.Locked:
_insult = "{0}, {1}".format(" ".join(msg[4].split()[1:]), insult())
sock.say(msg[3], _insult)
Locker.Lock()
else:
sock.notice(msg[3], "Please wait a little longer before using this command again.")


hooks = {
'^@insult': [gen, 5, False],
'^@insult': [gen, 5, False],
}

helpstring = "Insults someone/something. Polls insultgenerator.org for an insult."
helpstring = "@insult - Insults someone/something. Polls insultgenerator.org for an insult."
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python
import os
from random import choice

@@ -1,5 +1,7 @@
#!/usr/bin/python2
#!/usr/bin/env python
import requests
from CommandLocker import Locker
Locker = Locker(3)
'''
Poll automeme.net for a 'meme'.
Usage: import Meme, m = Meme.meme(), next(m)
@@ -25,7 +27,7 @@ def get_meme(t):
meme_db.append(meme)
meme_db.pop()
return meme_db

def meme(t):
'''Returns a meme from the list'''
meme_db = []
@@ -42,13 +44,21 @@ def meme(t):

def RegMeme(msg, sock, users, allowed):
try:
sock.say(msg[3], next(RegularMeme))
if not Locker.Locked:
sock.say(msg[3], next(RegularMeme))
Locker.Lock()
else:
sock.notice(msg[0], "Please wait a little longer and try again")
except Exception, e:
print("* [AutoMeme] Error:\n* [AutoMeme] {0}".format(str(e)))

def HipMeme(msg, sock, users, allowed):
try:
sock.say(msg[3], next(HipsterMeme))
if not Locker.Locked:
sock.say(msg[3], next(HipsterMeme))
Locker.Lock()
else:
sock.notice(msg[0], "Please wait a little longer and try again")
except Exception, e:
print("* [AutoMeme] Error:\n* [AutoMeme] {0}".format(str(e)))

@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python
'''This module will contain misc commands so they are not scattered around.'''
from threading import Timer
from random import randint
@@ -9,36 +9,36 @@ def Act(msg, sock, users, allowed):
sock.action(msg[3], "slaps {0} upside the head".format(msg[0]))
else:
sock.action(msg[3], x)

def Oven(msg, sock, users, allowed):
person = " ".join(msg[4].split()[1:])
sock.send("PRIVMSG {0} :\x01ACTION prepares his ovens\x01".format(msg[3]))
t = Timer(randint(7,11), sock.send, ("PRIVMSG {0} :\x01ACTION ovens {1}\x01".format(msg[3], person), ))
sock.action(msg[3], "prepares his ovens")
t = Timer(randint(7,11), sock.action, (msg[3], "ovens {0}".format(person)))
t.daemon = True
t.start()

def Next(msg, sock, users, allowed):
sock.say(msg[3], "Another satisfied customer! Next!")

def Bacon(msg, sock, users, allowed):
person = " ".join(msg[4].split()[1:])
if person == '':
person = 'Ferus'
sock.send("PRIVMSG {0} :\x01ACTION cooks up some fancy bacon for {1}\x01".format(msg[3], person))
sock.action(msg[3], "cooks up some fancy bacon for {0}".format(person))

def Hug(msg, sock, users, allowed):
access = allowed.levelCheck(msg[0])[1][1]
if access <= 4:
sock.say(msg[3], "\x01ACTION hugs {0}.\x01".format(msg[0]))
sock.action(msg[3], "hugs {0}.".format(msg[0]))
else:
sock.say(msg[3], "\x01ACTION kicks {0} in the balls for not being a man.\x01".format(msg[0]))
sock.action(msg[3], "kicks {0} in the balls for not being a man.".format(msg[0]))

def Echo(msg, sock, users, allowed):
sock.say(msg[3], msg[4][6:])

def Raw(msg, sock, users, allowed):
sock.send(msg[4][5:])

hooks = {
'^@oven': [Oven, 5, False],
'^@next': [Next, 5, False],
@@ -1,32 +1,32 @@
#!/usr/bin/python2
#!/usr/bin/env python
import os
import time

try:
import mpd
except ImportError:
print("Please install python-mpd to use this plugin or remove/rename it. ./Plugins/MpdScript.py")
print("* [Mpd] Please install python-mpd to use this plugin or remove/rename it. ./Plugins/MpdScript.py")


hostname = "localhost"
port = 6601

client = mpd.MPDClient()
# client.currentsong() will return a dictionary with song info
# 'album' # The album the song is from
# 'composer' # The composer
# 'artist' # The artist
# 'track' # The track
# 'title' # The title
# 'pos' # The position in the playlist
# 'id' # The id
# 'album' # The album the song is from
# 'composer' # The composer
# 'artist' # The artist
# 'track' # The track
# 'title' # The title
# 'pos' # The position in the playlist
# 'id' # The id
# 'last-modified' # The last time the file was modified
# 'albumartist' # The album artist
# 'file' # The full path of the file
# 'time' # The current time of the song
# 'date' # Date of the song/album
# 'genre' # Genre of song
# 'disc' # Disc number
# 'albumartist' # The album artist
# 'file' # The full path of the file
# 'time' # The current time of the song
# 'date' # Date of the song/album
# 'genre' # Genre of song
# 'disc' # Disc number

def mpd_connect():
try:
@@ -42,25 +42,25 @@ def mpd_disconnect():
client.disconnect() # disconnect from the server
except:
print("* [MPD] Couldn't disconnect from MPD server.")

def mpdshow_cb(t=True):
if mpd_connect():
current_song = client.currentsong()
current_status = client.status()
song_filename = os.path.basename(current_song["file"])
(song_shortname, song_extension) = os.path.splitext(song_filename)
(song_pos,song_length) = current_status["time"].split(":")

song_pos = time.strftime('%M:%S', time.gmtime(float(song_pos)))
song_length = time.strftime('%M:%S', time.gmtime(float(song_length)))

if t:
song_s = "({0}/{1})".format(song_pos, song_length)
else:
song_s = ''

mpd_disconnect()
try:
try:
return "Now Playing: {0} - {1} - {2} {3}".format(current_song["artist"], current_song["album"], current_song["title"], song_s)
except:
return "Now Playing: {0} {1}".format(song_shortname,song_s)
@@ -70,7 +70,7 @@ def mpdshow_cb(t=True):
def mpdprev_cb():
mpd_connect()
client.previous()
mpd_disconnect()
mpd_disconnect()
return mpdshow_cb(t=False)

def mpdnext_cb():
@@ -93,9 +93,9 @@ def Music(msg, sock, users, allowed):
sock.say(msg[3], mpdprev_cb())
except Exception, e:
print("* [MPD] Error:\n* [MPD] {0}".format(str(e)))

hooks = {
'^@mpd': [Music, 0, True],
'^@mpd': [Music, 0, True],
}

helpstring = """Gives the owner control over MPD, a music playing daemon.
@@ -1,22 +1,23 @@
#!/usr/bin/python2
#!/usr/bin/env python
import random
import re
from threading import Timer

from CommandLock import Locker

class Plinko(object):
def __init__(self):
'''
Challenged to write a plinko plugin.
A great game from The Price Is Right.
However, I'm fairly sure this will be pretty spammy.
'''
random.seed(__import__("os").urandom(30))
random.seed(__import__("os").urandom(30)) #Don't do this ok.
self.Head = "|_._._._._._._._._|"
self.Tail = "|._._._._._._._._.|"
self.End = "|_|_|_|_|_|_|_|_|_|"
self.isHead = True
self.Location = None
self.Locked = False

self.GoLeftHead = {
"1":"1", #Cant go left.
@@ -103,15 +104,6 @@ def Trigger(self):
self.isHead = False
else:
self.isHead = True

def Lock(self):
if not self.Locked:
self.Locked = True
t = Timer(5, self.UnLock, ())
t.daemon = True
t.start()
def UnLock(self):
self.Locked = False

def Start(self, StartLocation):
if type(StartLocation) != int:
@@ -133,12 +125,13 @@ def Start(self, StartLocation):
return Game

Pl = Plinko()
Locker = Locker()

def Parse(Msg, Sock, Users, Allowed):
if Msg[3] not in chans:
Sock.notice(Msg[0], "Go back to #games faggot.")
return None
if Pl.Locked:
if Locker.Locked:
Sock.notice(Msg[0], "Locked. Try again in a few seconds.")
return None
try:
@@ -156,7 +149,7 @@ def Parse(Msg, Sock, Users, Allowed):
x = 5
for line in Pl.Start(x):
Sock.say(Msg[3], line)
Pl.Lock()
Locker.Lock()
try:
for x in prizes[str(Pl.Location)]:
exec(x)
@@ -177,7 +170,7 @@ def Parse(Msg, Sock, Users, Allowed):
'2' : ["Sock.say(Msg[3], '{0}'.format(random.choice(phrases)))"],
'3' : ["Sock.say(Msg[3], '{0}'.format(random.choice(phrases)))"],
'4' : ["Sock.say(Msg[3], '!tkb {0} 2m You fucking suck.'.format(Msg[0]))", "t = Timer(125, Sock.invite, (Msg[0], Msg[3],))", "t.daemon = True", "t.start()"],
'5' : ["Sock.say(Msg[3], '!access add {0} 5'.format(Msg[0]))", "t = Timer(300, Sock.say, (Msg[3], '!access del {0}'.format(Msg[0]),))", "t.daemon = True", "t.start()"],
'5' : ["Sock.op(Msg[3], Msg[0])", "t = Timer(300, Sock.deop, (Msg[3], Msg[0],))", "t.daemon = True", "t.start()"],
'6' : ["Sock.say(Msg[3], '!tkb {0} 2m You fucking suck.'.format(Msg[0]))", "t = Timer(125, Sock.invite, (Msg[0], Msg[3],))", "t.daemon = True", "t.start()"],
'7' : ["Sock.say(Msg[3], '{0}'.format(random.choice(phrases)))"],
'8' : ["Sock.say(Msg[3], '{0}'.format(random.choice(phrases)))"],
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python
from random import choice
import cPickle as pickle
import os, re
@@ -108,12 +108,13 @@ def Search(self, msg=''):
if re.search(msg, quote, re.IGNORECASE):
_quotenums.append(str(num+1))

if len(_quotenums) == 1:
return "I found 1 quote matching the string '{0}': Quote number {1}".format(msg, _quotenums[0])

elif len(_quotenums) > 1:
return "I found {0} quotes matching the string '{1}': Quote numbers {2}".format(len(_quotenums), msg, ", ".join(_quotenums))

if len(_quotenums) >= 1:
return "I found {0} quote{1} matching the string '{2}': Quote number{1} {3}".format(
len(_quotenums),
"s" if len(_quotenums) > 1 else "",
msg,
", ".join(_quotenums))

elif len(_quotenums) == 0:
return "I did not find any quotes matching the string '{0}': Please redefine your search.".format(msg)

@@ -0,0 +1,11 @@
#!/usr/bin/python2
from random import randint

def roll():
return "".join([randint(0,6), randint(0,6)])

hooks = {
'^@doubles': [roll, 5, False],
}

helpstring = "Get your doubles here"
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python
import random

class Slap(object):
@@ -46,7 +46,7 @@ def Parse(self, Msg, Sock, Users, Allowed):
#No random
Sock.action(Msg[3], "slaps {0} around a bit with {1}.".format(tmp[0], " ".join(tmp[1:])))

except IndexError:
except:
Sock.notice(Msg[0], "@slap takes two arguments. The person and the object. Either can be 'random'")

S = Slap("Plugins/Fish.txt")
@@ -1,21 +1,28 @@
#!/usr/bin/python2
#!/usr/bin/env python
import requests
from CommandLock import Locker
Locker = Locker(5)

def get_slogan(text):
r = requests.post('http://www.sloganmaker.com/sloganmaker.php', data={'user':text})
if r.status_code == 200:
return "\x02[SloganMaker]\x02 {0}".format(r.content.split('<p>')[1].split('</p>')[0])
else:
print("* [SloganMaker] Error - Status Code {0}".format(r.status_code))
return "\x02[SloganMaker]\x02 Error; Status Code {0}".format(r.status_code)

def Slogan(msg, sock, users, allowed):
try:
sock.say(msg[3], get_slogan(" ".join(msg[4].split()[1:])))
if not Locker.Locked:
sock.say(msg[3], get_slogan(" ".join(msg[4].split()[1:])))
Locker.Lock()
else:
sock.notice(msg[0], "Please wait a little longer before using this command again")
except Exception, e:
print("* [SloganMaker] Error:\n* [SloganMaker] {0}".format(str(e)))

hooks = {
'^@slogan': [Slogan, 5, False],
'^@slogan': [Slogan, 5, False],
}

helpstring = "@slogan <string> returns a 'slogan' from SloganMaker.com"
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python
import requests
from htmldecode import convert

@@ -1,5 +1,5 @@
#!/usr/bin/python2
#Tinyboard thread stats checker.
#!/usr/bin/env python
#Tinyboard thread stats checker.

import re
import requests
@@ -8,7 +8,7 @@
class Tinyboard(object):
'''
A 'simple' module that returns stats of a thread. Post count, Image count, and the OP's text.
If the link contains a hash (#) in the end (A direct link to a specific post),
If the link contains a hash (#) in the end (A direct link to a specific post),
it will return that posts text rather than the OP.
'''
def GetHtml(self, link):
@@ -23,13 +23,13 @@ def GetHtml(self, link):
return html
except:
return None

def Parse(self, link):
link = link.replace("mod.php?/", "")
link = link.replace("mod.php?/", "")
html = self.GetHtml(link)
if html == None:
return "Error'd: {0}".format(link)

imageCount = html.count("<p class=\"fileinfo\">") #Number of images
postCount = html.count("<div class=\"post reply\"") #Number of post replies

@@ -39,7 +39,7 @@ def Parse(self, link):
imageText = "no images"
else:
imageText = "1 image"

if postCount > 1:
postText = "{0} replies".format(postCount)
elif postCount == 0:
@@ -61,89 +61,89 @@ def Parse(self, link):
else:
Post_html = re.findall("<div class=\"post op\">", html)[0]
Post_html = html.split(Post_html)[1].split("</div>")[0]

try:
Post_Name = Post_html.split("<span class=\"name\">")[1].split("</span>")[0].strip(" ")
except:
Post_Name = "Anonymous"

try:
Post_Trip = Post_html.split("<span class=\"trip\">")[1].split("</span>")[0].strip(" ")
except:
Post_Trip = None

try:
Post_CapCode = Post_html.split("<a class=\"capcode\">")[1].split("</a>")[0].strip(" ")
except:
Post_CapCode = None

Post_Text = re.findall("<p class=\"body\">(.*?)</p>", Post_html)[0]

#Replace heading html with irc bold and red color.
Headings = re.findall("<span class=\"heading\">(.*?)<\/span>", Post_Text)
for Heading in Headings:
Post_Text = re.sub("<span class=\"heading\">{0}<\/span>".format(Heading), "\x02\x0305{0}\x03\x02".format(Heading), Post_Text)

#Replace spoiler html with irc black on black text.
Spoilers = re.findall("<span class=\"spoiler\">(.*?)<\/span>", Post_Text)
for Spoiler in Spoilers:
Post_Text = re.sub("<span class=\"spoiler\">{0}<\/span>".format(Spoiler), "\x0301,01{0}\x03".format(Spoiler), Post_Text)

#Replace all italics html with irc underlines.
Italics = re.findall("<em>(.*?)<\/em>", Post_Text)
for Italic in Italics:
Post_Text = re.sub("<em>{0}<\/em>".format(Italic), "\x1f{0}\x1f".format(Italic), Post_Text)

#Replace all bold html with irc bold.
Bolds = re.findall("<strong>(.*?)<\/strong>", Post_Text)
for Bold in Bolds:
Post_Text = re.sub("<strong>{0}<\/strong>".format(Bold), "\x02{0}\x02".format(Bold), Post_Text)

#Replace all greentext lines with green irc color.
Implys = re.findall("<span class=\"quote\">(.*?)<\/span>", Post_Text)
for Imply in Implys:
Post_Text = re.sub("<span class=\"quote\">{0}<\/span>".format(Imply), "\x0303{0}\x03".format(Imply), Post_Text)

Post_Text = Post_Text.replace("<br/>"," ")
Post_Text = Post_Text.replace("&gt;",">")

if re.search("<a target=\"_blank\" rel=\"nofollow\" href=\".*?\">.*?</a>", Post_Text):
Link_html = re.findall("<a target=\"_blank\" rel=\"nofollow\" href=\".*?\">.*?</a>", Post_Text)

for _link in Link_html:
_link = re.split("<a target=\"_blank\" rel=\"nofollow\" href=\".*?\">", _link)[1]
_link = re.split("</a>", _link)[0]
Post_Text = re.sub("<a target=\"_blank\" rel=\"nofollow\" href=\".*?\">.*?</a>", _link, Post_Text)


if re.search("<a onclick=\"highlightReply\('[0-9]{1,}'\);\" href=\".*?\.html#[0-9]{1,}\">>>[0-9]{1,}</a>", Post_Text):
Link_Num = re.findall(">>[0-9]{1,}<", Post_Text)[0][:-1]
Post_Text = re.sub("<a onclick=\"highlightReply\('[0-9]{1,}'\);\" href=\".*?\.html#[0-9]{1,}\">>>[0-9]{1,}</a>", Link_Num, Post_Text)

Post_Text = self.smart_truncate(Post_Text)
Post_Text = convert(Post_Text)

if Post_Trip:
return "{0}{1} ({2}, {3}) posted: {4} - {5}".format(Post_Name, Post_Trip, postText, imageText, Post_Text, link)
elif Post_CapCode:
return "{0} {1} ({2}, {3}) posted: {4} - {5}".format(Post_Name, Post_CapCode, postText, imageText, Post_Text, link)
else:
return "{0} ({1}, {2}) posted: {3} - {4}".format(Post_Name, postText, imageText, Post_Text, link)

def smart_truncate(self, content, length=300, suffix='...'):
'''Borrowed from stackoverflow, Credits to 'Adam'. :) '''
if len(content) <= length:
return content
else:
x = ' '.join(content[:length+1].split(' ')[0:-1]) + suffix
return x

def Main(self, link=None):
try:
return self.Parse(link)
except:
return None

TB = Tinyboard()

def TinyboardLink(msg, sock, users, allowed):
@@ -152,14 +152,12 @@ def TinyboardLink(msg, sock, users, allowed):
for y in re.findall(x, msg[4]):
if y not in links:
links.append(y)

for link in links:
x = TB.Main(link)
if x != None:
sock.say(msg[3], x)
sock.say(msg[3], TB.Main(link))

hooks = {
'https?:\/\/(?:www\.)?4chon\.net\/(?:mod\.php\?\/)?[a-zA-Z0-9]{1,}(?:\/res)?\/[0-9]{1,}\.html(?:#[0-9]{1,})?': [TinyboardLink, 5, False],
'(?:https?:\/\/)?(?:www\.)?4chon\.net\/(?:mod\.php\?\/)?[a-zA-Z0-9]{1,}(?:\/res)?\/[0-9]{1,}\.html(?:#[0-9]{1,})?': [TinyboardLink, 5, False],
}

helpstring = "A tinyboard parsing plugin. Parses any link that matches a regex as defined by the owner."
@@ -1,18 +1,18 @@
#!/usr/bin/python2
#!/usr/bin/env python
from random import choice

class Told(object):
def __init__(self, ToldFile=None):
if ToldFile:
with open(ToldFile, "r") as Tolds:
self.ToldList = Tolds.readlines()

def ReturnTold(self, msg, sock, users, allowed):
sock.send("PRIVMSG {0} :{1}".format(msg[3], choice(self.ToldList)))
sock.say(msg[3], choice(self.ToldList))

t = Told("Plugins/Told.txt")
hooks = {
'^@told': [t.ReturnTold, 5, False],
'^@told': [t.ReturnTold, 5, False],
}

helpstring = "Sends a random 'Told' string"
helpstring = "@told: Sends a random 'Told' string"
@@ -1,8 +1,10 @@
#!/usr/bin/python2
#!/usr/bin/env python

import requests
import os, re
from htmldecode import convert
from CommandLock import Locker
Locker = Locker(5)
# http://www.urbandictionary.com/tooltip.php?term= <-- Thank god for this url.

def request(word):
@@ -22,7 +24,7 @@ def request(word):
escapes = re.compile(r'[\r\n\t]')
try:
result = content.match(escapes.sub('', html.replace("<br/>", " ").strip())).groups()[1]
except:
except:
result = None
if not result or result is None or result == '':
return "\x02[UrbanDict]\x02 {0} has not yet been defined.".format(word)
@@ -42,7 +44,7 @@ def cached(word):
return False
except:
return False

def add_cache(word, definition=''):
if os.access('./Plugins/UrbanDict_Cache.txt', 6):
with open('./Plugins/UrbanDict_Cache.txt','a') as c:
@@ -53,15 +55,19 @@ def add_cache(word, definition=''):
print('* [UrbanDict] Cache => Creating Cache')
print('* [UrbanDict] Cache => Adding word {0}'.format(word))
c.write("{0} : {1}\n".format(word, definition))

def UD(msg, sock, users, allowed):
try:
sock.say(msg[3], request(" ".join(msg[4].split()[1:])))
if not Locker.Locked:
sock.say(msg[3], request(" ".join(msg[4].split()[1:])))
Locker.Lock()
else:
sock.notice(msg[0], "Please wait a little bit longer before using this command")
except Exception, e:
print("* [UrbanDict] Error:\n* [UrbanDict] {0}".format(str(e)))

hooks = {
'^@ud': [UD, 5, False],
'^@ud': [UD, 5, False],
}

helpstring = "Polls UrbanDictionary for a word if that word is not already in the local cache"
helpstring = "@ud <Word>: Polls UrbanDictionary for a word if that word is not already in the local cache"
@@ -1,3 +1,5 @@
#!/usr/bin/env python

# Wikipedia article retriever plugin for WhergBot
# 1.0; 01.01.2012; Edza

@@ -6,6 +8,7 @@

# This is a very simple initial version.

# Feb 06 - Added a Command Locker
# Jan 11 - Removed Footnotes from text
# Jan 11 - Fixed a bug with missing 'http://' for requests
# Jan 11 - Removed Unicode bug
@@ -14,6 +17,8 @@
import requests
import os, re
from htmldecode import convert
from CommandLock import Locker
Locker = Locker(5)

def truncate(content, length=300, suffix='...'):
if len(content) <= length:
@@ -27,36 +32,36 @@ def getArticleByName(articleName):
return "{0} - {1}".format(getArticleByUrl(Url), Url)

def getArticleByUrl(articleUrl):
if not articleUrl.startswith("http://"):
articleUrl = "http://{0}".format(articleUrl)
if not articleUrl.startswith("http://") and not articleUrl.startswith("https://"):
articleUrl = "https://{0}".format(articleUrl)
try:
articleHtml = requests.get(articleUrl).content
except:
print("* [Wikipedia] Error => Failed to connect.")
return "Failed to connect to Wikipedia."

titleRegex = re.compile("<title>(.*?) -")
firstParaRegex = re.compile("<p>(.*?)[\r\n]?<\/p>")
footnoteRegex = re.compile("\[[0-9]{1,3}\]")

# Special cases
disambRegex = re.compile('may refer to:$')
notfoundRegex = re.compile('Other reasons this message may be displayed:')

try:
title = re.sub('<[^<]+?>', '', titleRegex.search(articleHtml).group())
text = re.sub('<[^<]+?>', '', firstParaRegex.search(articleHtml).group())
text = footnoteRegex.sub('', text)

text = truncate(text).encode("utf-8")

if disambRegex.search(text):
text = "Disambiguations are not yet supported."
elif notfoundRegex.search(text):
text = "Article not found."

result = "{0} {1}".format(title, text)
except:
except:
result = "Failed to retrieve the Wikipedia article."

return result
@@ -72,8 +77,12 @@ def wikiUrl(msg, sock, users, allowed):

def wikiName(msg, sock, users, allowed):
try:
article = " ".join(msg[4].split()[1:])
sock.say(msg[3], "\x02[Wikipedia]\x02 {0}".format(getArticleByName(article)))
if not Locker.Locked:
article = " ".join(msg[4].split()[1:])
sock.say(msg[3], "\x02[Wikipedia]\x02 {0}".format(getArticleByName(article)))
Locker.Lock()
else:
sock.notice(msg[0], "Please wait a little longer before using this command again.")
except Exception, e:
print("* [Wikipedia] Error:\n* [Wikipedia] {0}".format(str(e)))

@@ -1,13 +1,16 @@
#!/usr/bin/python2
#!/usr/bin/env python
#Youtube Stats/Link Parser

import requests
import json
import decimal
import re

from CommandLock import Locker
from htmldecode import convert

Lock = Locker(5)

class YT(object):
def Main(self, vidId):
if not vidId:
@@ -30,35 +33,35 @@ def ConvertTime(self, seconds):
duration += "{0}:".format(str(hours).zfill(2))
duration += "{0}:{1}".format(str(minutes).zfill(2), str(seconds).zfill(2))
return duration

def Parse(self, jsonReply):
D = decimal.Decimal
TWOPLACES = D('0.01')

totalvotes = int(jsonReply['entry']['gd$rating']['numRaters'])
perc = (D(jsonReply['entry']['gd$rating']['average']) / int(jsonReply['entry']['gd$rating']['max'])).quantize(TWOPLACES)

try:
likes = int(jsonReply['entry']['yt$rating']['numLikes'])
dislikes = int(jsonReply['entry']['yt$rating']['numDislikes'])
except:
likes = int(totalvotes*float(perc))
dislikes = int(totalvotes-likes)

title = jsonReply['entry']['title']['$t'].encode('utf-8')
duration = self.ConvertTime(int(jsonReply['entry']['media$group']['yt$duration']['seconds']))

stats = {
'title':convert(title),
'author':convert(str(jsonReply['entry']['author'][0]['name']['$t'])),

'averagerating':D(jsonReply['entry']['gd$rating']['average']).quantize(TWOPLACES),
'maxrating':int(jsonReply['entry']['gd$rating']['max']),
'maxrating':int(jsonReply['entry']['gd$rating']['max']),
'percentrating':str(perc).replace(".","").lstrip("0"),
'totalvotes':totalvotes,
'likes':likes,
'dislikes':dislikes,

'duration':duration,
'viewcount':"{:1,}".format(int(jsonReply['entry']['yt$statistics']['viewCount'])),
'favorites':int(jsonReply['entry']['yt$statistics']['favoriteCount']),
@@ -88,46 +91,58 @@ def Search(self, terms, results=2):
VidLink = "https://youtu.be/"+vidInfo['id']['$t'].split(":")[-1]
VidLikes = vidInfo['yt$rating']['numLikes']
VidDisLikes = vidInfo['yt$rating']['numDislikes']
VidLength = vidInfo['media$group']['yt$duration']['seconds']
VidLength = self.ConvertTime(int(VidLength))

VidLength = self.ConvertTime(int(vidInfo['media$group']['yt$duration']['seconds']))

# <Title + Uploader> [Length] <Link> [Average/Max Likes/Dislikes] <Views>
info = "\x02[YouTube]\x02 Title: \x02{0}\x02 - By: \x02{1}\x02".format(VidTitle, Uploader)
info += " [Length: \x02{0}\x02] <Link: {1}>".format(VidLength, VidLink)
info += " [Rating: \x02{0}\x02/\x02{1}\x02]".format(VidAverage, VidMax)
info += " <(Dis)Likes: \x02{0}\x02/\x02{1}\x02>".format(VidLikes, VidDisLikes)
info += " [Views: \x02{0}\x02]".format(VidViewCounts)
info = "\x02[YouTube]\x02 Title: \x02{0}\x02".format(VidTitle) if VidTitle else ""
info += "- By: \x02{0}\x02".format(Uploader) if Uploader else ""
info += " [Length: \x02{0}\x02]".format(VidLength) if VidLength else ""
info += " <Link: {0}>".format(VidLink) if VidLink else ""
info += " [Rating: \x02{0}\x02/\x02{1}\x02]".format(VidAverage, VidMax) if VidAverage and VidMax else ""
info += " <(Dis)Likes: \x02{0}\x02/\x02{1}\x02>".format(VidLikes, VidDisLikes) if VidLikes and VidDisLikes else ""
info += " [Views: \x02{0}\x02]".format(VidViewCounts) if VidViewCounts else ""
results.append(info)
return results

YouTube = YT()

def youtubestats(msg, sock, users, allowed):
def YouTubeStats(msg, sock, users, allowed):
vidId = re.findall("=[a-zA-Z0-9_\-]{11}", msg[4])[0][1:]
x = YouTube.Main(vidId)
x = YT.Main(vidId)
if x != None:
# [YouTube] title - By: author {duration} <averagerating/maxrating (percentrating%)> [x Likes/x Dislikes/x Total]
head = "\x02[YouTube]\x02 {0} - By: \x02{1}\x02 [\x02{2}\x02]".format(x['title'], x['author'], x['duration'])
middle = "<\x02{0}\x02/\x02{1}\x02 (\x02{2}%\x02) \x02{3}\x02 Views>".format(x['averagerating'], x['maxrating'], x['percentrating'], x['viewcount'])
tail = "[\x02{0}\x02 Likes/\x02{1}\x02 Dislikes/\x02{2}\x02 Total]".format(x['likes'], x['dislikes'], x['totalvotes'])

y = "{0} {1} {2}".format(head, middle, tail)
sock.say(msg[3], y)
info = "\x02[YouTube]\x02 {0}".format(x['title'] if x['title'] else '')
# Still want to keep the [YouTube] even if the title wasnt found. (Which shouldn't happen.)
info += " - By: \x02{0}\x02".format(x['author']) if x['author'] else ''
info += " [\x02{0}\x02]".format(x['duration']) if x['duration'] else ''
info += " \x02{0}\x02/\x02{1}\x02 (\x02{2}%\x02)".format(x['averagerating'], x['maxrating'], x['percentrating']) \
if x['averagerating'] and x['maxrating'] and x['percentrating'] else ''

info += " \x02{0}\x02 Views".format(x['viewcount']) if x['viewcount'] else ''
info += " \x02{0}\x02 Likes".format(x['likes']) if x['likes'] else ''
info += " \x02{0}\x02 Dislikes".format(x['dislikes']) if x['dislikes'] else ''
info += " \x02{0}\x02 Total".format(x['totalvotes']) if x['totalvotes'] else ''

sock.say(msg[3], info)
else:
pass

def YouTubeGetVids(msg, sock, users, allowed):
if Lock.Locked:
sock.notice(msg[0], "Please wait a few seconds before using this command again.")
return None
try:
terms = "+".join(msg[4].split()[1:]).replace("|","%7C")
except:
sock.say(msg[3], "Supply some searchterms you derp!")
for vid in YouTube.Search(terms, results=1):
for vid in YouTube.Search(terms, results=3):
sock.say(msg[3], vid)

Lock.Lock()

hooks = {
'(?:https?:\/\/)?(?:www\.)?youtube\.com\/': [youtubestats, 5, False],
'(?:https?:\/\/)?(?:www\.)?youtube\.com\/': [YouTubeStats, 5, False],
'^@yt': [YouTubeGetVids, 5, False],
}
}

helpstring = """Polls for youtube video info based on a regex.
@yt <string>: Searches for a video and returns the first, along with some stats."""
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python
#Taken from http://www.evaisse.net/2008/python-html-entities-decode-cgi-unescape-7002
#because Python can't into having some decode function to do it.

@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python
import shelve

class Allowed():
@@ -1,20 +1,20 @@
#!/usr/bin/python2
#!/usr/bin/env python

class HostServ(object):
'''Hostserv On/Off controls.'''
def __init__(self, sock=None):
if sock:
self.sock = sock

def On():
def On(self):
print("* [HostServ] Turning vHost on.")
self.sock.say("HostServ", "On")

def Off():
def Off(self):
print("* [HostServ] Turning vHost off.")
self.sock.say("HostServ", "Off")

def Request(vHost):
def Request(self, vHost):
if vHost:
print("* [HostServ] Requesting vHost.")
self.sock.say("HostServ", "Request {0}".format(vHost))
@@ -1,18 +1,22 @@
#!/usr/bin/python2
#!/usr/bin/env python
from getpass import getpass

class NickServ(object):
'''Nickserv controls.'''
def __init__(self, sock=None):
self.password = getpass("* [NickServ] Enter bot's NickServ pass. (Blank for no pass): ")

try:
self.password = getpass("* [NickServ] Enter bot's NickServ pass. (Blank for no pass): ")
except EOFError:
print("")
self.password = ''

if sock:
self.sock = sock

def Identify(self):
print("* [NickServ] Identifying to NickServ.")
self.sock.say("NickServ", "Identify {0}".format(self.password))

def Update():
def Update(self):
print("* [NickServ] Updating.")
self.sock.say("NickServ", "Update")
@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python

class Users(object):
def __init__(self):
@@ -1,38 +1,200 @@
#!/usr/bin/python2

import Core
from threading import Timer

nick = 'WhergBot'
real = 'WhergBot [Ferus]'
ident = 'Wherg'
#channels = ['#hacking', '#lobby' ,'#4chon' ,'#circlejerk' ,'#tinyboard' ,'#animu', '#games', "#h"]
channels = ['#h']
owner = ['Ferus', 'anonymous@the.interwebs', 0]

server = 'localhost'
proxy = ("127.0.0.1", 3125, "socks5")
ssl = True
if ssl:
port = 7001
else:
port = 7000
#!/usr/bin/env python

import os
from ConfigParser import ConfigParser

_CONFIGDEFAULTS = {
"nick" : "WhergBot"
,"real" : "Wherg"
,"ident" : "Wherg"
,"ownernick" : "Ferus"
,"ownerhost" : "anonymous@the.interwebs"
,"owneraccess" : "0"
,"usessl" : "False"
,"logging" : "False"
,"server" : "opsimathia.datnode.net"
,"port" : "6667"
,"sslport" : "6697"
,"channels" : "#hacking"
,}

def LoadConfig(Profile='WhergBot'):
"""Load the config file (If we can access it)
If we can't, we make one."""
if os.access("./Config.ini", 6):
Config = ConfigParser(defaults=_CONFIGDEFAULTS)
Config.read("./Config.ini")
print("* [Config] Config file found. Loading config.")
if not Config.has_section(Profile):
import sys
sys.exit("* [Config] No profile found with the name '{0}'. Please re-run WhergBot with the -r flag to make it.".format(Profile))
return Config
else:
print("* [Config] No Config.ini file found. Would you like to create one now?")
if raw_input("[Y/N] >> ").lower() not in ('y', 'yes'):
import sys
sys.exit("* [Config] You have chosen not to create a config file now. Run WhergBot.py with the -n flag to regenerate a config.")
else:
return MakeConfig()

def MakeConfig():
"""Makes a new config.ini / Profile"""
print("* [Config] You have chosen to (re-)create the config file.")
Prof = ConfigParser(defaults=_CONFIGDEFAULTS)
Prof.add_section('WhergBot')
Prof = SetConfig(Prof, 'WhergBot')

with open("./Config.ini", 'wb') as C:
Prof.write(C)
print("* [Config] Wrote config file to Config.ini.")
return Prof

def NewProfile():
Prof = ConfigParser(defaults=_CONFIGDEFAULTS)
Prof.read("./Config.ini")
print("* [Config] First off, what would you like to name the new profile?")

NewConfig = GetAnswer(Prompt="New profile name >> ", isStr=True)
print("* [Config] You have chosen to name the profile '{0}'.".format(NewConfig))

Prof.add_section(NewConfig)
Prof = SetConfig(Prof, NewConfig)

with open("./Config.ini", 'wb') as C:
Prof.write(C)

print("* [Config] New profile has been written, Be sure to specify it when running with `WhergBot.py -p {0}`".format(NewConfig))
return NewConfig

def SetConfig(Prof=None, ProfileName=''):
"""Ask the user for profile options"""
print("* [Config] What will the bots' nickname be?")
Prof.set(ProfileName, 'Nick', GetAnswer(Prompt="Enter Bots' Name >> "))

print("* [Config] What will the bots' realname be?")
Prof.set(ProfileName, 'Real', GetAnswer(Prompt="Enter Bots' Realname >> "))

print("* [Config] What will the bots' ident be?")
Prof.set(ProfileName, 'Ident', GetAnswer(Prompt="Enter Bots' Ident >> "))

print("* [Config] What channels will the bot join on start? (Separate with a comma)")
Prof.set(ProfileName, 'Channels', GetAnswer(Prompt="Enter Channels (IE: `#lobby,#bots`) >> "))

print("* [Config] What is the name of the bots' Owner? (Likely your nick.)")
Prof.set(ProfileName, 'OwnerNick', GetAnswer(Prompt="Enter Owners IRC Nick >> "))

print("* [Config] What is the hostmask of the bots' Owner? (Likely your hostmask.)")
Prof.set(ProfileName, 'OwnerHost', GetAnswer(Prompt="Enter Owners Hostmask >> "))

print("* [Config] What is the default access level of the owner? (If unsure, enter 0)")
Prof.set(ProfileName, 'OwnerAccess', GetAnswer(Prompt="Enter Owners Access Level >> "))

print("* [Config] What server will we be connecting to on start?")
Prof.set(ProfileName, 'Server', GetAnswer(Prompt="Enter Server Address >> "))

print("* [Config] Will we be using SSL to connect? (If unsure, enter 'False')")
Prof.set(ProfileName, 'UseSSL', GetAnswer(Prompt="Enter SSL choice (True/False) >> ", isBool=True))

print("* [Config] What port will be used with SSL? (Default 6697)")
Prof.set(ProfileName, 'SSLPort', GetAnswer(Prompt="Enter default SSL port >> ", isInt=True))

print("* [Config] What port will be used without SSL? (Default 6667)")
Prof.set(ProfileName, 'Port', GetAnswer(Prompt="Enter default Non-SSL port >> ", isInt=True))

print("* [Config] Will we be logging connections? (Default False)")
Prof.set(ProfileName, 'Logging', GetAnswer(Prompt="Enter choice for logging (True/False) >> ", isBool=True))
return Prof


def GetAnswer(Prompt=">> ", isInt=False, isBool=False):
"""DrunkCode.py"""
try:
x = raw_input(Prompt)
if not x or len(x) == 0:
print("* [Config] You cannot pass a blank argument.")
return GetAnswer()

if isInt:
if not x.isdigit():
print("* [Config] This setting takes an int type. You entered '{0}' which is not an int.".format(x))
return GetAnswer(isInt=True)
else: x = int(x)

if isBool:
if x.lower() in ('true', 't'):
return 'True'
elif x.lower() in ('false', 'f'):
return 'False'
else:
print("* [Config] This setting takes a bool type. You entered '{0}' which is not a bool.".format(x, type(x)))
return GetAnswer(isBool=True)
return x
except EOFError:
print("\n* [Config] That input was not valid.")
return GetAnswer(isInt=isInt, isBool=isBool)


if __name__ == '__main__':
import sys
if not sys.stdout.isatty():
sys.exit("Not a terminal bud. Don't have a GUI made yet. ;)")
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-n", "--new-config", dest="Newfile", action="store_true", default=False, help="Generate a new config file")
parser.add_option("-r", "--new-profile", dest="Newprof", action="store_true", default=False, help="Add a new profile to the config")
parser.add_option("-p", "--profile", dest="Profile", help="Specify a profile")
(options, args) = parser.parse_args()

if options.Newfile and options.Profile or \
options.Newfile and options.Newprof or \
options.Profile and options.Newprof:
sys.exit("You cannot specify multiple flags.")

if options.Profile:
Profile = options.Profile

if options.Newprof:
Profile = NewProfile()

if options.Newfile:
if os.access("./Config.ini", 6):
if raw_input("* [Config] Would you like to backup the old config file?\n[Y/N] >> ").lower() in ("y","yes"):
os.rename("./Config.ini", "./Config.ini.bak")
print("* [Config] Backed up the old config file.")
else:
os.remove("./Config.ini")
print("* [Config] We will not backup the old config file.")
Profile = 'WhergBot'

Config = LoadConfig(Profile)
print("* [Config] Using profile '{0}'.".format(Profile))

for key in _CONFIGDEFAULTS.keys():
if not Config.has_option(Profile, key):
sys.exit("* [Config] Missing option in config file, '{0}'.".format(key))

import Core
from threading import Timer
WhergBot = Core.Bot(
nickname = Config.get(Profile, "nick"),
realname = Config.get(Profile, "real"),
ident = Config.get(Profile, "ident"),
owner = [Config.get(Profile, "ownernick"), Config.get(Profile, "ownerhost"), Config.getint(Profile, "owneraccess")],
ssl = Config.getboolean(Profile, "usessl"),
proxy = None,
logging = Config.getboolean(Profile, "logging"))

try:
WhergBot = Core.Bot(nick, real, ident, owner, ssl, proxy=proxy)
WhergBot.Connect(server=server, port=port)
if WhergBot.Nickserv.password != '':
_p = Timer(3, WhergBot.Identify, ())
_p.daemon = True
_p.start()
_t = Timer(5, WhergBot.irc.join, (",".join(channels),))
port = Config.getint(Profile, 'port') if not Config.getboolean(Profile, 'usessl') else Config.getint(Profile, 'sslport')
WhergBot.Connect(server=Config.get(Profile, "server"), port=port)
_t = Timer(5, WhergBot.irc.join, (Config.get(Profile, "Channels"),))
_t.daemon = True
_t.start()
_t.start()

while WhergBot.irc._isConnected:
WhergBot.Parse(WhergBot.irc.recv(bufferlen=1024))

Msg = WhergBot.irc.recv()
WhergBot.Parse(Msg)

except KeyboardInterrupt:
print("\n* [Core] Interrupt Caught; Quitting!")
WhergBot.p.command.Quit("KeyboardInterrupt Caught!")
@@ -1,3 +1,9 @@
=== Feb 15 ===
+ i am git and wat is dis
=== Feb 03 ===
+ Some changes reflecting upon latest requests and blackbox
+ #!/usr/bin/python2 -> #!/usr/bin/env python
+ Removed lock from Plinko.py and turned it into CommandLock.py to be shared.
=== Jan 12 ===
+ @help/@plugins command and helpstrings
=== Jan 09 ===
@@ -24,7 +30,7 @@
=== Dec 01 ===
+ Plugins now take the non-optional 'users' and 'allowed' in the called functions
+'users' is an Users.Users() object that holds the userlist for each channel.
+'allowed' is an Allowed.Users() object that holds access levels, allowing each
+'allowed' is an Allowed.Users() object that holds access levels, allowing each
plugin to 'bypass' set access levels.
+ A Services folder, used for network Services like NickServ and HostServ
+ Optional NickServ pass on start.
@@ -1,12 +1,12 @@
1: Change how the parser handles messages, and more options
1: Define more hooks for the parser

2: Move everything to a config file?

3: Woll Smoth mode.
Override blackbox.send()
2: Woll Smoth mode.
Override blackbox.send()?
Use regex to replace all vowels in recv'd lines with o

4: Fix CTCP printing, apparently started since the parser was revamped
3: Fix CTCP printing, apparently started since the parser was revamped

4: Change Owner to a list/dict to allow multiple owners.

#### PLUGINS ####

@@ -1,3 +1,5 @@
#!/usr/bin/env python

# This program is Free Software under the terms of
# the Do What The Fuck You Want To Public License (WTFPL)
# See wtfpl.txt or http://sam.zoy.org/wtfpl/COPYING
@@ -44,8 +46,7 @@ def load(folder):
[module])
except Exception as e:
print("=================================")
print("An error occured trying to import {0}:"
.format(module))
print("An error occured trying to import {0}:".format(module))
print(repr(e))
print("Ignored. Fix this shit bro.")
print("Moving on...")