user: adam
passwd: moo
db: pypsd
-sock: /var/lib/mysql/mysql.sock
[ctcp]
nick: py-ctcp
key_lastfm: xxx
key_fml: xxx
key_wolframalpha: xxx
+key_steam: xxx
[limitserv]
nick: Limitserv
user=config.get('database', 'user'),
passwd=config.get('database', 'passwd'),
db=config.get('database', 'db'),
- unix_socket=config.get('database', 'sock')
)
dbx.autocommit(True) # no need to have transactions
dbp = dbx.cursor()
-Subproject commit e2d4ad88b2d45dbf8351082d458dff8f35e775a4
+Subproject commit fc8f03599b2609e239c7571b366968824676a0ba
import ConfigParser
import codecs
from istring import istring
-import MySQLdb as db
import logging
import logging.handlers
+import pool
config = ConfigParser.ConfigParser()
config.readfp(codecs.open("config.ini", "r"))
if anope_major not in [1, 2]:
raise Exception('Unknown anope major version %s' % anope_major)
-dbx = db.connect(
- host=config.get('database', 'host'),
- user=config.get('database', 'user'),
- passwd=config.get('database', 'passwd'),
- db=config.get('database', 'db'),
- unix_socket=config.get('database','sock')
-)
-dbx.ping(True)
-dbx.autocommit(True) #no need to have transactions
+dbpool = pool.DBPool(config)
+dbx = dbpool.get_connection()
logfile = config.get('logging', 'logfile')
loglevel = getattr(logging, config.get('logging', 'level').upper())
class StdOutWriter(object):
def write(self, what):
- # print is Python keyword, so call println with what.strip() instead of print
- javasys.out.println(what.rstrip())
+ # print is a Python keyword
+ javasys.out['print'](what)
class StdErrWriter(object):
def write(self, what):
- javasys.err.println(what.rstrip())
+ javasys.err['print'](what)
sys.stdout = StdOutWriter()
sys.stderr = StdErrWriter()
from operator import itemgetter #for sort
from collections import defaultdict
import time
+import re
from pyva import *
import logging
Acidictive.privmsg(self.client, target, "END OF VLIST (%d results)" % count)
return True
+
+ # Version regex check link to see what it does:
+ # http://regexper.com/#%28%28%3F%3A\%28%3Fv%3F\d%2B\.[^\s]%2B\%29%3F%29|%28%3F%3AClient%3A\d%2B%3A\d%2B%29%29
+ versionRegex = re.compile("\(?v?(\d+\.[\d\.\-A-z]+)\)?|(Client:\d+:\d+)")
+ nameRegex = re.compile("([http://]*[\.\w+]+)")
+ # regex to strip control codes + colour codes from messages.
+ controlRegex = re.compile(u'([\u0000-\u0002\u0004-\u001F]|\u0003\d{1,2}(?:,\d{1,2}){0,1})')
+
+ def cmd_ctcpCurrentVersionList(self, source, target, pieces):
+ hasLimit = False
+ showVersions = False
+ limit = 25
+
+ for piece in pieces:
+ if hasLimit == False:
+ try:
+ limit = int(piece)
+ hasLimit = True
+ continue
+ except ValueError:
+ limit = 25
+ if showVersions == False and piece.lower() == "+versions":
+ showVersions = True
+
+ version_list = [];
+
+ def compare(item1, item2):
+ return item2['count'] - item1['count']
+
+ def select(list, key, value, newItem):
+ for item in list:
+ if item[key] == value:
+ return item
+ else:
+ list.append(newItem)
+ return newItem
+
+ for user in User.getUsersC():
+ try:
+ cv = self.controlRegex.sub("", user['version'])
+ clientVersion = self.versionRegex.search(cv)
+ clientName = nameRegex.search(cv)
+ try:
+ clientName = clientName.group(0)
+ except:
+ continue
+ item = select(version_list, 'name', clientName, { 'name': clientName, 'count': 0, 'versions': [] })
+ item['count'] += 1
+ if clientVersion.group(1) != None:
+ v = clientVersion.group(1)
+ version = select(item['versions'], 'version', v, { 'version': v, 'count': 0 })
+ version['count'] += 1
+ except AttributeError:
+ continue
+
+ version_list.sort(cmp=compare)
+
+ counter = 0
+
+ for item in version_list:
+ Acidictive.privmsg(self.client, target, u"%s [%s %s]" % (item['name'], item['count'], 'time' if item['count'] == 1 else 'times'))
+ if showVersions:
+ item['versions'].sort(cmp=compare)
+ for version in item['versions']:
+ Acidictive.privmsg(self.client, target, u" %s [%s %s]" % (version['version'], version['count'], 'time' if version['count'] == 1 else 'times'))
+
+ counter += 1
+ if counter >= limit:
+ return
## End Command hooks
'permission': 'v',
'callback': self.cmd_ctcpVersionList,
'usage': "{top|search} [num|searchstring] - shows the top client version replies or searches them. Defaults to showing top"}),
+ ('cvlist', {
+ 'permission': 'v',
+ 'callback': self.cmd_ctcpCurrentVersionList,
+ 'usage': "[limit] [+versions] - Shows the client types, and their version numbers (when +versions is provided as argument), currently online. Default limit is 25."}),
)
from datetime import datetime, timedelta
from xml.parsers.expat import ExpatError
+import core
from pseudoclient.cmd_manager import *
from utils import *
from internets_utils import *
def get_citystate_from_zipcode(self, zipcode):
"""Return [city,state] for the given U.S. zip code (if database has been imported)"""
try:
- self.dbp.execute("SELECT city, state FROM zipcode_citystate WHERE zipcode=%s", [int(zipcode)])
- city, state = self.dbp.fetchone()
- return city, state
+ con = core.dbpool.get_connection()
+ try:
+ cursor = con.cursor()
+ cursor.execute("SELECT city, state FROM zipcode_citystate WHERE zipcode=%s", [int(zipcode)])
+ city, state = cursor.fetchone()
+ return city, state
+ finally:
+ core.dbpool.put_connection(con)
except:
return None
self.elog.debug('Started core subsystems.')
self.initialized = True
- self.msg('HostServ', 'WAITING') # Check if we missed requests while down
+ if Acidictive.me and not Acidictive.me.isBursting():
+ self.msg('HostServ', 'WAITING') # Check if we missed requests while down
return True
self.logchan = config.get('control', 'channel')
self.log = logging.getLogger(__name__)
self.config = config
- self.dbp = dbx.cursor()
+ self.dbp = dbx.cursor() # do these have to be closed?
def start(self):
pass
--- /dev/null
+import threading
+import MySQLdb as db
+
+class DBPool(object):
+ _lock = threading.RLock()
+ _connections = []
+
+ def __init__(self, conf):
+ self.config = conf
+ self.add_connection()
+
+ def add_connection(self):
+ con = db.connect(
+ host=self.config.get('database', 'host'),
+ user=self.config.get('database', 'user'),
+ passwd=self.config.get('database', 'passwd'),
+ db=self.config.get('database', 'db'),
+ )
+ con.ping(True)
+ con.autocommit(True) #no need to have transactions
+
+ with self._lock:
+ self._connections.append(con)
+
+ def get_connection(self):
+ with self._lock:
+ if len(self._connections) == 0:
+ self.add_connection()
+ return self._connections.pop()
+
+ def put_connection(self, con):
+ with self._lock:
+ if con not in self._connections:
+ self._connections.append(con)
+
+
from utils import *
import pyva_net_rizon_acid_core_User as User
-import pyva_net_rizon_acid_core_Channel as Channe;
+import pyva_net_rizon_acid_core_Channel as Channel
def build_ban_message(entity):
message = 'Source: @b%s@b.' % entity.ban_source
import threading
-import MySQLdb as db
+import core
class Subsystem(object):
#--------------------------------------------------------------#
self.reload()
def db_open(self):
- self.conn = db.connect(
- host=self.module.config.get('database', 'host'),
- user=self.module.config.get('database', 'user'),
- passwd=self.module.config.get('database', 'passwd'),
- db=self.module.config.get('database', 'db'),
- unix_socket=self.module.config.get('database','sock')
- )
- self.conn.ping(True)
- self.conn.autocommit(True)
+ self.conn = core.dbpool.get_connection()
self.cursor = self.conn.cursor()
def db_close(self):
self.cursor = None
if self.conn != None:
- self.conn.close()
+ core.dbpool.put_connection(self.conn)
self.conn = None
def reload(self):
+import pyva_net_rizon_acid_core_Acidictive as Acidictive
+
IRCCOLOR_WHITE = 0
IRCCOLOR_BLACK = 1
IRCCOLOR_BLUE = 2
if level > self.level:
return
- self.module.msg(self.chan, '@c%d[%d] %s@o' % (color, level, message))
+ if Acidictive.me and not Acidictive.me.isBursting():
+ self.module.msg(self.chan, '@c%d[%d] %s@o' % (color, level, message))
self.notice(sender, args[1] + " is not a valid quote number.")
return
+ if len(args) == 1:
+ self.notice(sender, "Please specify quote number to delete.")
+ return
+
self.notice(sender, "Checking if you are the channel founder.")
self.auth.request(sender, channel, 'delete_quote' + args[1])
for i, row in enumerate(self.dbp.fetchall()):
# i+1 = 1 should equal out[0]
out.append("%d. %s %d" % (i+1, row[0], row[1]))
-
- self.notice(sender, '; '.join(out))
+
+ if len(out) == 0:
+ self.notice(sender, "No one has played yet.")
+ else:
+ self.notice(sender, '; '.join(out))
elif command == 'rank':
if arg != '':
querynick = arg.lower()
else:
querynick = sender.lower()
- # Select user and user above this user in scoring list.
- querystring = "SELECT x.nick, x.position, x.points, x.channel FROM (SELECT t.nick, t.points, t.channel, @rownum := @rownum + 1 AS position FROM trivia_scores AS t JOIN (SELECT @rownum := 0) r ON t.channel = %s ORDER BY t.points DESC) x WHERE x.nick >= %s ORDER BY x.position DESC LIMIT 2;"
-
- self.dbp.execute(querystring, (self.get_cid(channel), querynick))
+ self.dbp.execute("SELECT nick, points FROM trivia_scores WHERE channel = %s ORDER BY points DESC;", (self.get_cid(channel),))
rows = self.dbp.fetchall()
- if len(rows) >= 1 and rows[0][0].lower() == querynick:
- userdata = rows[0]
- out = "%s is currently ranked #%d with %d %s" % (userdata[0], userdata[1], userdata[2], "point" if userdata[2] == 1 else "points")
- if len(rows) == 2:
- otherdata = rows[1]
- diff = otherdata[2] - userdata[2]
- out += ", %d %s behind %s" % (diff, "point" if diff == 1 else "points", otherdata[0])
- out += "."
- self.notice(sender, out)
+ for i in range(len(rows)):
+ userdata = rows[i]
+ if userdata[0].lower() == querynick.lower():
+ out = "%s is currently ranked #%d with %d %s" % (userdata[0], i + 1, userdata[1], "point" if userdata[1] == 1 else "points")
+ if i > 0:
+ otherdata = rows[i - 1]
+ diff = otherdata[1] - userdata[1]
+ out += ", %d %s behind %s" % (diff, "point" if diff == 1 else "points", otherdata[0])
+ out += "."
+ self.notice(sender, out)
+ break
else:
self.notice(sender, "Nickname not found.")
#elif command == 'next': # Defunct in orig trivia