port to new balun ircrobots framework
This commit is contained in:
parent
c7746b72d2
commit
04e7b7c064
8 changed files with 258 additions and 182 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,3 +5,5 @@
|
|||
sizelog
|
||||
*journal
|
||||
|
||||
auth.py
|
||||
|
||||
|
|
188
bot.py
188
bot.py
|
@ -1,102 +1,134 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import asyncio, os, importlib
|
||||
|
||||
import pydle, asyncio, dataset, sys, os, time
|
||||
from irctokens import build, Line
|
||||
from ircrobots import Bot as BaseBot
|
||||
from ircrobots import Server as BaseServer
|
||||
from ircrobots import ConnectionParams, SASLUserPass, SASLSCRAM
|
||||
|
||||
class Kim(pydle.Client):
|
||||
async def on_connect(self):
|
||||
print('Connected!')
|
||||
from auth import username, password
|
||||
import shared
|
||||
|
||||
self.modules = {}
|
||||
self.cmd = {}
|
||||
self.rawm = {}
|
||||
self.help = {}
|
||||
self.db = dataset.connect('sqlite:///database.db')
|
||||
self.t=0
|
||||
def is_admin(func):
|
||||
async def decorator(self,channel,nick,msg):
|
||||
if nick.lower() in self.users and self.users[nick.lower()].account in self.admins:
|
||||
await func(self,channel,nick,msg)
|
||||
else:
|
||||
await message(self,'core',channel,'you do not have permission to do that')
|
||||
return decorator
|
||||
|
||||
print('loading modules...')
|
||||
await self.loadMods()
|
||||
print('joining channels')
|
||||
for i in self.chansjoin:
|
||||
await self.join(i)
|
||||
print('Done!')
|
||||
|
||||
# tilde +B bot
|
||||
await self.set_mode(self.nickname, '+B')
|
||||
#def is_chanop(func):
|
||||
|
||||
|
||||
async def loadMods(self):
|
||||
for i in [s for s in os.listdir('modules') if ".py" in s and '.swp' not in s]:
|
||||
i = i[:-3]
|
||||
print('loading', i)
|
||||
m = __import__("modules."+i)
|
||||
m = eval('m.'+i)
|
||||
await m.init(self)
|
||||
self.modules[i] = m
|
||||
def command(commandname):
|
||||
def decorator(func):
|
||||
shared.commands[commandname] = func
|
||||
return func
|
||||
return decorator
|
||||
|
||||
async def on_invite(self, channel, by):
|
||||
await self.modules['invite'].invite(self, channel, by)
|
||||
# print('{} invited me to {}!'.format(by, channel))
|
||||
# self.t = time.time()+1
|
||||
# await self.join(channel)
|
||||
def listener(listenername):
|
||||
def decorator(func):
|
||||
shared.listeners.append((listenername, func))
|
||||
return func
|
||||
return decorator
|
||||
|
||||
def rawm(rname):
|
||||
def decorator(func):
|
||||
shared.rawm[rname] = func
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
async def on_message(self, chan, source, msg):
|
||||
if chan == self.nickname:
|
||||
chan = source
|
||||
if source != self.nickname:
|
||||
|
||||
async def message(self,modname,channel,msg):
|
||||
await self.send(build("PRIVMSG",[channel,f'[\x036{modname}\x0f] {msg}']))
|
||||
|
||||
|
||||
if time.time() > self.t:
|
||||
|
||||
|
||||
if msg == '!botlist':
|
||||
await self.message(chan, 'helo im kim, a learning chatbot https://tildegit.org/xfnw/kim/')
|
||||
await self.parseCommand(chan, source, msg)
|
||||
for i in self.rawm:
|
||||
await self.rawm[i](self, chan, source, msg)
|
||||
|
||||
async def parseCommand(self, chan, source, msg):
|
||||
if msg[:len(self.prefix)] == self.prefix:
|
||||
|
||||
msg = msg[len(self.prefix):]
|
||||
cmd = msg.split(' ')[0]
|
||||
msg = msg[len(cmd)+1:]
|
||||
if len(cmd) < 1:
|
||||
return
|
||||
class Server(BaseServer):
|
||||
async def line_read(self, line: Line):
|
||||
print(f"{self.name} < {line.format()}")
|
||||
if 'on_'+line.command.lower() in dir(self):
|
||||
asyncio.create_task(self.__getattribute__('on_'+line.command.lower())(line))
|
||||
for listener in shared.listeners:
|
||||
if listener[0] == line.command:
|
||||
asyncio.create_task(listener[1](self,line))
|
||||
|
||||
if cmd in self.cmd:
|
||||
await self.cmd[cmd](self, chan, source, msg)
|
||||
return
|
||||
|
||||
# fuzzy search for commands
|
||||
results = [i for i in self.cmd if i.startswith(cmd)]
|
||||
if len(results) == 1:
|
||||
await self.cmd[results[0]](self, chan, source, msg)
|
||||
async def line_send(self, line: Line):
|
||||
print(f"{self.name} > {line.format()}")
|
||||
|
||||
|
||||
async def is_admin(self, nickname):
|
||||
async def on_001(self, line):
|
||||
asyncio.create_task(self.load_modules())
|
||||
|
||||
# Check the WHOIS info to see if the source has identified with NickServ.
|
||||
# This is a blocking operation, so use yield.
|
||||
info = await self.whois(nickname)
|
||||
if 'account' in info:
|
||||
account = info['account']
|
||||
else:
|
||||
# they are not nickserv registered
|
||||
return False
|
||||
|
||||
return account in self.admins
|
||||
async def load_modules(self):
|
||||
for i in [s for s in os.listdir('modules') if '.py' in s and '.swp' not in s]:
|
||||
i = i[:-3]
|
||||
m = importlib.import_module('modules.' + i)
|
||||
asyncio.create_task(m.init(self))
|
||||
shared.modules[i] = m
|
||||
|
||||
#async def on_private_message(self, trash, source, msg):
|
||||
# if source != self.nickname:
|
||||
# for i in self.rawm:
|
||||
# await self.rawm[i](self, source, source, msg)
|
||||
# depricated, to support old modules
|
||||
async def message(self,channel,msg):
|
||||
await self.send(build("PRIVMSG",[channel,msg]))
|
||||
|
||||
|
||||
async def on_privmsg(self, line):
|
||||
if line.tags and "batch" in line.tags and line.tags["batch"] == '1':
|
||||
return
|
||||
|
||||
|
||||
channel = line.params[0]
|
||||
nick = line.source.split('!')[0]
|
||||
msg = line.params[1]
|
||||
|
||||
if channel == self.nickname:
|
||||
channel = nick
|
||||
|
||||
await self.handle_rawm(channel,nick,msg)
|
||||
await self.handle_command(channel,nick,msg)
|
||||
async def handle_rawm(self,channel,nick,msg):
|
||||
for i in shared.rawm:
|
||||
await shared.rawm[i](self,channel,nick,msg)
|
||||
async def handle_command(self,channel,nick,msg):
|
||||
if msg[:len(shared.prefix)] == shared.prefix:
|
||||
msg = msg[len(shared.prefix):]
|
||||
cmd = msg.split(' ')[0]
|
||||
msg = msg[len(cmd)+1:]
|
||||
if len(cmd) < 1:
|
||||
return
|
||||
|
||||
if cmd in shared.commands:
|
||||
await shared.commands[cmd](self,channel,nick,msg)
|
||||
return
|
||||
|
||||
results = [i for i in shared.commands if i.startswith(cmd)]
|
||||
if len(results) == 1:
|
||||
await shared.commands[results[0]](self,channel,nick,msg)
|
||||
|
||||
|
||||
class Bot(BaseBot):
|
||||
def create_server(self, name: str):
|
||||
return Server(self, name)
|
||||
|
||||
|
||||
async def main():
|
||||
bot = Bot()
|
||||
|
||||
sasl_params = SASLUserPass(username, password)
|
||||
params = ConnectionParams(
|
||||
"kim",
|
||||
host = "irc.tilde.chat",
|
||||
port = 6697,
|
||||
tls = True,
|
||||
sasl = sasl_params)
|
||||
|
||||
await bot.add_server("tilde", params)
|
||||
await bot.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
client = Kim('kim', realname='owens bot')
|
||||
client.admins = ['lickthecheese', 'ben', 'coffeeowl', 'gbmor', 'tomasino', 'ubergeek', 'deepend', 'calamitous', 'khuxkm']
|
||||
client.prefix = 'kim: '
|
||||
client.run('team.tilde.chat', tls=True, tls_verify=False)
|
||||
|
||||
asyncio.run(main())
|
||||
|
||||
|
|
126
modules/admin.py
126
modules/admin.py
|
@ -1,52 +1,52 @@
|
|||
|
||||
import importlib, time, asyncio, pydle
|
||||
import importlib, time, asyncio, random
|
||||
from bot import *
|
||||
|
||||
quitmessages = [
|
||||
"time to die",
|
||||
'you can hide, but you can not run!',
|
||||
"you're next",
|
||||
'bye',
|
||||
'the balun has been popped.',
|
||||
]
|
||||
|
||||
|
||||
async def commit(self, chan, source, msg):
|
||||
await self.quit('{} told me to commit {}'.format(source,msg))
|
||||
|
||||
async def quit(self, chan, source, msg):
|
||||
await self.quit('{} told me to {}'.format(source,msg))
|
||||
await self.send(build("QUIT",[random.choice(quitmessages)]))
|
||||
|
||||
|
||||
|
||||
async def reloadmods(self, chan, source, msg):
|
||||
await self.message(chan, '[\x036admin\x0f] reloading modules...')
|
||||
self.oldcmd = self.cmd
|
||||
self.cmd = {}
|
||||
self.rawm = {}
|
||||
self.help = {}
|
||||
shared.oldcmd = shared.commands
|
||||
shared.commands = {}
|
||||
shared.rawm = {}
|
||||
shared.listeners = []
|
||||
shared.help = {}
|
||||
try:
|
||||
for i in self.modules:
|
||||
importlib.reload(self.modules[i])
|
||||
await self.modules[i].init(self)
|
||||
for i in shared.modules:
|
||||
importlib.reload(shared.modules[i])
|
||||
await shared.modules[i].init(self)
|
||||
#await self.message(chan, '[\x036admin\x0f] load {} sucess!'.format(i))
|
||||
await self.message(chan, '[\x036admin\x0f] done! {} modules reloaded!'.format(len(self.modules)))
|
||||
await self.message(chan, '[\x036admin\x0f] done! {} modules reloaded!'.format(len(shared.modules)))
|
||||
except:
|
||||
await self.message(chan, '[\x036admin\x0f] reload failed... attempting to recover...')
|
||||
self.cmd = self.oldcmd
|
||||
shared.commands = shared.oldcmd
|
||||
|
||||
|
||||
async def part(self, chan, source, msg):
|
||||
await self.message(chan, '[\x036admin\x0f] bye {}'.format(msg))
|
||||
await self.part(msg)
|
||||
|
||||
async def join(self, chan, source, msg):
|
||||
self.t = time.time()+1
|
||||
await self.message(chan, '[\x036admin\x0f] joined {}'.format(msg))
|
||||
await self.join(msg)
|
||||
async def rawcmd(self, chan, source, msg):
|
||||
await self.send_raw(msg)
|
||||
|
||||
async def joins(self, chan, source, msg):
|
||||
await self.message(chan, '[\x036admin\x0f] I will drop commands for some seconds to ignore chanhistory...')
|
||||
await self.message(chan, '[\x036admin\x0f] joining slowly as to not flood...')
|
||||
for i in self.chandb.all():
|
||||
self.t = time.time() + 5
|
||||
try:
|
||||
await self.join(i['name'])
|
||||
await asyncio.sleep(3)
|
||||
print('joined {}'.format(i['name']))
|
||||
except pydle.client.AlreadyInChannel:
|
||||
print('I am already in {}'.format(i['name']))
|
||||
await asyncio.sleep(3)
|
||||
await self.message(chan, '[\x036admin\x0f] Sucess!')
|
||||
await self.send(build("JOIN",[i['name']]))
|
||||
await asyncio.sleep(1)
|
||||
print('joined {}'.format(i['name']))
|
||||
await self.message(chan, '[\x036admin\x0f] Sucess! i may be laggy for a bit while i sort through all these channels...')
|
||||
|
||||
async def aexec(self, code):
|
||||
# Make an async function with the code and `exec` it
|
||||
|
@ -74,7 +74,7 @@ async def send(self, c, n, m):
|
|||
await self.message(c, '[\x036admin\x0f] sent')
|
||||
|
||||
async def shut(self, c, n, m):
|
||||
self.qtime[c] = time.time()+(60*10)
|
||||
shared.qtime[c] = time.time()+(60*10)
|
||||
await self.message(c, '[\x036admin\x0f] Ok, il be back in 10 minutes')
|
||||
|
||||
async def schans(self, c, n, m):
|
||||
|
@ -94,11 +94,56 @@ async def addalias(self,c,n,m):
|
|||
await self.message(c,'[\x036admin\x0f] added "{}" alias for "{}"'.format(al,m))
|
||||
|
||||
|
||||
async def addot(self,c,n,m):
|
||||
al = m.split(' ')[0]
|
||||
m = m[len(al)+1:] # dont use the list since i want trailing spaces
|
||||
if al in self.rawm:
|
||||
await self.message(c,'[\x036admin\x0f] no dont overwrite a command dummy')
|
||||
return
|
||||
self.rawm[al]=Ot(m,al).ot
|
||||
|
||||
await self.message(c,'[\x036admin\x0f] added "{}" trigger for "{}"'.format(al,m))
|
||||
|
||||
|
||||
|
||||
async def addtrigger(self,c,n,m):
|
||||
al = m.split(' ')[0]
|
||||
m = m[len(al)+1:] # dont use the list since i want trailing spaces
|
||||
if al in self.rawm:
|
||||
await self.message(c,'[\x036admin\x0f] no dont overwrite a command dummy')
|
||||
return
|
||||
self.rawm[al]=Trigger(m,al).trigger
|
||||
|
||||
await self.message(c,'[\x036admin\x0f] added "{}" trigger for "{}"'.format(al,m))
|
||||
|
||||
|
||||
|
||||
class Ot():
|
||||
def __init__(self, ms, al):
|
||||
self.ms = str(ms)
|
||||
self.al = str(al)
|
||||
async def ot(alself,self,c,n,m):
|
||||
if alself.al in m and n != self.nickname:
|
||||
asyncio.create_task(self.on_message(c,n,alself.ms.format(m)))
|
||||
self.rawm.pop(alself.al)
|
||||
|
||||
|
||||
|
||||
|
||||
class Trigger():
|
||||
def __init__(self, ms, al):
|
||||
self.ms = str(ms)
|
||||
self.al = str(al)
|
||||
async def trigger(alself,self,c,n,m):
|
||||
if alself.al in m:
|
||||
asyncio.create_task(self.on_message(c,n,alself.ms.format(m)))
|
||||
|
||||
|
||||
class Alias():
|
||||
def __init__(self, ms):
|
||||
self.ms = str(ms)
|
||||
async def alias(alself,self,c,n,m):
|
||||
asyncio.create_task(self.parseCommand(c,n,alself.ms.format(m)))
|
||||
asyncio.create_task(self.on_message(c,n,alself.ms.format(m)))
|
||||
|
||||
|
||||
|
||||
|
@ -106,30 +151,33 @@ commands = {
|
|||
'quit': quit,
|
||||
'reload': reloadmods,
|
||||
'commit': commit,
|
||||
'part': part,
|
||||
'join': join,
|
||||
'raw': rawcmd,
|
||||
'eval': ev,
|
||||
'send': send,
|
||||
'joins': joins,
|
||||
'shut': shut,
|
||||
'schans': schans,
|
||||
'addalias': addalias
|
||||
'addalias': addalias,
|
||||
'addtrigger': addtrigger,
|
||||
'addot': addot,
|
||||
}
|
||||
|
||||
@command('admin')
|
||||
@is_admin
|
||||
async def adminHandle(self, chan, source, msg):
|
||||
if await self.is_admin(source):
|
||||
msg = msg.split(' ')
|
||||
if len(msg) < 1 or not msg[0] in commands:
|
||||
await self.message(chan, '[\x036admin\x0f] Invalid command')
|
||||
return
|
||||
print('[ADMIN MODULE] {} told me to {}!!!'.format(source,msg[0]))
|
||||
await commands[msg.pop(0)](self, chan, source, ' '.join(msg))
|
||||
else:
|
||||
await self.message(chan, '[\x036admin\x0f] You do not have permission to do this')
|
||||
asyncio.create_task(commands[msg.pop(0)](self, chan, source, ' '.join(msg)))
|
||||
|
||||
|
||||
async def init(self):
|
||||
self.chandb = self.db['chan']
|
||||
self.chandb = shared.db['chan']
|
||||
|
||||
self.admins = ['lickthecheese']
|
||||
return
|
||||
self.cmd['admin'] = adminHandle
|
||||
|
||||
self.help['admin'] = ['admin - various bot owner commands (more for subcommands)', 'sub-commands of admin, for more info do help admin <command>: quit reload commit part join joins eval send']
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
async def action(self,c,n,m):
|
||||
await self.message(c,'\x01ACTION {}\x01'.format(m[:400]))
|
||||
|
||||
|
||||
async def echo(self,c,n,m):
|
||||
await self.message(c,'[\x036channels\x0f] {}'.format(m[:400]))
|
||||
|
||||
async def init(self):
|
||||
self.chansjoin = ['#bots']
|
||||
|
||||
self.cmd['echo']=echo
|
||||
self.cmd['action']=action
|
||||
|
||||
|
||||
|
|
@ -1,26 +1,9 @@
|
|||
import time
|
||||
|
||||
async def invite(self, channel, by):
|
||||
|
||||
if self.db['invite'].find_one(blacklist=channel):
|
||||
print('{} invited me to {}, a blacklisted channel'.format(by,channel))
|
||||
return
|
||||
|
||||
if self.db['invite'].find_one(enabled='true'):
|
||||
|
||||
print('{} invited me to {}!'.format(by, channel))
|
||||
self.t = time.time()+1
|
||||
await self.join(channel)
|
||||
else:
|
||||
if self.chandb.find_one(name=channel):
|
||||
self.t = time.time()+1
|
||||
await self.join(channel)
|
||||
print('whee invited to {} by {}'.format(channel,by))
|
||||
return
|
||||
|
||||
print('ive been invited but invites are disabled')
|
||||
from bot import *
|
||||
|
||||
@listener('INVITE')
|
||||
async def on_invite(self,line):
|
||||
self.send(build("JOIN",[line.params[1]]))
|
||||
|
||||
async def init(self):
|
||||
pass
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
from bot import *
|
||||
|
||||
import dataset
|
||||
import random
|
||||
import time
|
||||
|
||||
async def rec(self, m):
|
||||
prew = self.db['prew']
|
||||
noch = self.db['noun']
|
||||
beg = self.db['beg']
|
||||
end = self.db['end']
|
||||
prew = shared.db['prew']
|
||||
noch = shared.db['noun']
|
||||
beg = shared.db['beg']
|
||||
end = shared.db['end']
|
||||
pre = ''
|
||||
words = m.split(' ')
|
||||
if words[0] == 'admin':
|
||||
|
@ -22,20 +23,20 @@ async def rec(self, m):
|
|||
end.insert(dict(word=pre))
|
||||
|
||||
async def getNoun(self, words, c):
|
||||
if c in self.cstate:
|
||||
oldnoun = self.cstate[c]
|
||||
if c in shared.cstate:
|
||||
oldnoun = shared.cstate[c]
|
||||
else:
|
||||
oldnoun = None
|
||||
|
||||
self.db['remsg'].insert_ignore(dict(noun=oldnoun,msg=' '.join(words)),['id'])
|
||||
shared.db['remsg'].insert_ignore(dict(noun=oldnoun,msg=' '.join(words)),['id'])
|
||||
|
||||
nouns = [i['word'] for i in self.db['noun'].find()]
|
||||
nouns = [i['word'] for i in shared.db['noun'].find()]
|
||||
out = {}
|
||||
for i in words:
|
||||
out[i] = nouns.count(i)
|
||||
noun = min(out, key=out.get)
|
||||
|
||||
conversation = self.db['conver']
|
||||
conversation = shared.db['conver']
|
||||
if oldnoun != None:
|
||||
print("adding", [oldnoun,noun])
|
||||
conversation.insert_ignore(dict(pre=oldnoun,pro=noun),['id'])
|
||||
|
@ -44,27 +45,27 @@ async def getNoun(self, words, c):
|
|||
print("nextnoun:",nextnoun)
|
||||
if len(nextnoun) > 0:
|
||||
noun = random.choice(nextnoun)
|
||||
self.cstate[c] = noun
|
||||
shared.cstate[c] = noun
|
||||
return noun
|
||||
|
||||
async def genOut(self, noun):
|
||||
oldresponses = [i['msg'] for i in self.db['remsg'].find(noun=noun)]
|
||||
oldresponses = [i['msg'] for i in shared.db['remsg'].find(noun=noun)]
|
||||
if len(oldresponses) > 0:
|
||||
return random.choice(oldresponses).split(' ')
|
||||
prew = self.db['prew']
|
||||
beg = [ i['word'] for i in self.db['beg'].find() ]
|
||||
end = [ i['word'] for i in self.db['end'].find() ]
|
||||
nouns = [i['word'] for i in self.db['noun'].find()]
|
||||
prew = shared.db['prew']
|
||||
beg = [ i['word'] for i in shared.db['beg'].find() ]
|
||||
end = [ i['word'] for i in shared.db['end'].find() ]
|
||||
nouns = [i['word'] for i in shared.db['noun'].find()]
|
||||
iter=0
|
||||
out = [noun]
|
||||
while (out[0] not in beg or nouns.count(out[0])-1 > iter * self.enmul) and iter < 7:
|
||||
while (out[0] not in beg or nouns.count(out[0])-1 > iter * shared.enmul) and iter < 7:
|
||||
try:
|
||||
out = [ random.choice(list(prew.find(pro=out[0])))['pre'] ] + out
|
||||
except IndexError:
|
||||
iter += 69
|
||||
iter += 1
|
||||
iter = 0
|
||||
while (out[-1] not in end or nouns.count(out[-1])-1 > iter * self.enmul) and iter < 7:
|
||||
while (out[-1] not in end or nouns.count(out[-1])-1 > iter * shared.enmul) and iter < 7:
|
||||
|
||||
try:
|
||||
out.append(random.choice(list(prew.find(pre=out[-1])))['pro'])
|
||||
|
@ -75,19 +76,19 @@ async def genOut(self, noun):
|
|||
|
||||
|
||||
async def filter(self, c, n, m):
|
||||
if self.t > time.time() or c in self.qtime and self.qtime[c] > time.time():
|
||||
if c in shared.qtime and shared.qtime[c] > time.time():
|
||||
return
|
||||
if m[:len(self.prefix)] == self.prefix:
|
||||
m = m[len(self.prefix):]
|
||||
if m[:len(shared.prefix)] == shared.prefix:
|
||||
m = m[len(shared.prefix):]
|
||||
await go(self, c, n, m)
|
||||
elif m[:4] == 'kim ':
|
||||
m = m[4:]
|
||||
await go(self, c, n, m)
|
||||
else:
|
||||
if len(m.split(' ')) > 1:
|
||||
if self.learntime + self.learndelay < time.time():
|
||||
if shared.learntime + shared.learndelay < time.time():
|
||||
await rec(self, m)
|
||||
self.learntime = time.time()
|
||||
shared.learntime = time.time()
|
||||
|
||||
async def go(self, c, n, m):
|
||||
await rec(self, m)
|
||||
|
@ -98,11 +99,11 @@ async def go(self, c, n, m):
|
|||
|
||||
async def init(self):
|
||||
|
||||
self.qtime = {}
|
||||
shared.qtime = {}
|
||||
|
||||
self.learntime = 0
|
||||
self.learndelay = 4
|
||||
self.enmul = 40
|
||||
self.rawm['nlp'] = filter
|
||||
shared.learntime = 0
|
||||
shared.learndelay = 4
|
||||
shared.enmul = 40
|
||||
shared.rawm['nlp'] = filter
|
||||
|
||||
self.cstate = {}
|
||||
shared.cstate = {}
|
||||
|
|
14
modules/test.py
Normal file
14
modules/test.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
import asyncio
|
||||
import bot
|
||||
|
||||
|
||||
@bot.command('test')
|
||||
@bot.is_admin
|
||||
async def testy(self,channel,nick,msg):
|
||||
await bot.message(self,'test',channel,'hi there')
|
||||
|
||||
async def init(self):
|
||||
|
||||
await self.send_raw("join #bots")
|
||||
|
||||
|
12
shared.py
Normal file
12
shared.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
import dataset
|
||||
|
||||
prefix = 'kim: '
|
||||
modules = {}
|
||||
listeners = []
|
||||
commands = {}
|
||||
rawm = {}
|
||||
db = dataset.connect('sqlite:///database.db')
|
||||
|
||||
qtime = {}
|
||||
|
Loading…
Reference in a new issue