Added pushbullet to summon, added in tasks/coroutines system, added in bbj integration
This commit is contained in:
parent
e7424f690b
commit
746ed85333
|
@ -1,9 +1,8 @@
|
|||
from actions.botlist import botlist
|
||||
from actions.summon import summon
|
||||
from actions.web import summon, whois
|
||||
from actions.access import banish, pardon
|
||||
from actions.control import puppet, nomad
|
||||
from actions.stupid import hmm, hmmscore, hmmscoreboard
|
||||
from actions.web import whois
|
||||
|
||||
actions = [
|
||||
{
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
from subprocess import Popen, PIPE
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
def summon(self, name, source, response):
|
||||
botnick = self.bot.botnick
|
||||
author = self.bot.author
|
||||
user, reason = response.split("!summon ")[1].split(" ", 1)
|
||||
|
||||
email = "{}@tilde.team"
|
||||
|
||||
message = MIMEText(" ".join([
|
||||
"My bot, {}, received a summoning request for you".format(botnick),
|
||||
"from {} in channel {} for reason: {}".format(name, source, reason)
|
||||
]))
|
||||
|
||||
message["From"] = email.format(botnick)
|
||||
message["To"] = email.format(user)
|
||||
message["Subject"] = "You have been summoned!"
|
||||
|
||||
command = "/usr/sbin/sendmail -t -oi".split(" ")
|
||||
p = Popen(command, stdin=PIPE, universal_newlines=True)
|
||||
p.communicate(message.as_string())
|
||||
|
||||
confirmation = "{}: You have summoned {}".format(name, user)
|
||||
self.bot.send_message(source, confirmation)
|
|
@ -1,7 +1,79 @@
|
|||
from subprocess import Popen, PIPE
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.parse import urlencode
|
||||
from urllib.error import HTTPError
|
||||
from json import loads
|
||||
|
||||
def get_iden(devices, device_name):
|
||||
for device in devices:
|
||||
if device.get("nickname", "") == device_name:
|
||||
return device.get("iden", "")
|
||||
|
||||
def push_note(bot, title, body):
|
||||
api_url = "https://api.pushbullet.com/v2"
|
||||
extra_settings = bot.settings.get("extras", dict())
|
||||
pb_settings = extra_settings.get("pushbullet", dict())
|
||||
api_key = pb_settings.get("api", "")
|
||||
device_name = pb_settings.get("device", "")
|
||||
|
||||
list_devices = Request("{}/devices".format(api_url))
|
||||
list_devices.add_header("Access-Token", api_key)
|
||||
|
||||
try:
|
||||
data = loads(urlopen(list_devices).read())
|
||||
except HTTPError:
|
||||
return
|
||||
|
||||
devices = data.get("devices", list())
|
||||
iden = get_iden(devices, device_name)
|
||||
|
||||
params = {
|
||||
"device_iden": iden,
|
||||
"type": "note",
|
||||
"title": title,
|
||||
"body": body
|
||||
}
|
||||
|
||||
post_params = urlencode(params).encode()
|
||||
|
||||
pushes = Request("{}/pushes".format(api_url), post_params)
|
||||
pushes.add_header("Access-Token", api_key)
|
||||
|
||||
try:
|
||||
response = loads(urlopen(pushes).read())
|
||||
except HTTPError as e:
|
||||
return
|
||||
|
||||
def summon(self, name, source, response):
|
||||
botnick = self.bot.botnick
|
||||
author = self.bot.author
|
||||
user, reason = response.split("!summon ")[1].split(" ", 1)
|
||||
|
||||
email = "{}@tilde.team"
|
||||
subject = "You have been summoned!"
|
||||
|
||||
text = " ".join([
|
||||
"My bot, {}, received a summoning request for you".format(botnick),
|
||||
"from {} in channel {} for reason: {}".format(name, source, reason)
|
||||
])
|
||||
message = MIMEText(text)
|
||||
|
||||
message["From"] = email.format(botnick)
|
||||
message["To"] = email.format(user)
|
||||
message["Subject"] = subject
|
||||
|
||||
command = "/usr/sbin/sendmail -t -oi".split(" ")
|
||||
p = Popen(command, stdin=PIPE, universal_newlines=True)
|
||||
p.communicate(message.as_string())
|
||||
|
||||
if user == author:
|
||||
push_note(self.bot, subject, text)
|
||||
|
||||
confirmation = "{}: You have summoned {}".format(name, user)
|
||||
self.bot.send_message(source, confirmation)
|
||||
|
||||
def whois(self, name, source, response):
|
||||
botnick = self.bot.botnick
|
||||
domain = response.split("!whois ")[1]
|
||||
|
|
24
app.py
24
app.py
|
@ -4,16 +4,17 @@ from os.path import dirname, realpath
|
|||
|
||||
from bot import Bot, Tasks, Responses
|
||||
from actions import actions
|
||||
from coroutines import coroutines
|
||||
|
||||
kingme = [
|
||||
"#chaos"
|
||||
]
|
||||
debug = False
|
||||
kingme = [] if debug else ["#chaos"]
|
||||
channels = ["#bots", "#insane"]
|
||||
# if not debug:
|
||||
# channels.extend([])
|
||||
|
||||
bot = Bot("127.0.0.1", 6667, "BabiliBot|py", [
|
||||
"#bots",
|
||||
"#insane"
|
||||
])
|
||||
bot = Bot("127.0.0.1", 6667, "BabiliBot|py", channels)
|
||||
responses = Responses(bot)
|
||||
tasks = Tasks(bot)
|
||||
|
||||
for action in actions:
|
||||
if "type" in action and "pattern" in action and "callback" in action:
|
||||
|
@ -23,6 +24,14 @@ for action in actions:
|
|||
action["callback"]
|
||||
)
|
||||
|
||||
# for coro in coroutines:
|
||||
# worker = coro["worker"]
|
||||
# interval = coro["interval"]
|
||||
# state = coro.get("state", None)
|
||||
# coro_state = state if state is not None else (bot,)
|
||||
# tasks.add_coroutine(worker, interval, coro_state)
|
||||
tasks.coroutines = coroutines
|
||||
|
||||
def try_to_king_me(channel):
|
||||
bot.send_message("ChanServ", "REGISTER {}", channel)
|
||||
bot.send_message("ChanServ", "SET Successor {} {}", channel, bot.botnick)
|
||||
|
@ -61,6 +70,7 @@ def handle_message(name, source, response):
|
|||
print("::", bot.memories)
|
||||
|
||||
if __name__ == "__main__":
|
||||
bot.tasks = tasks
|
||||
bot.start(dirname(realpath(__file__)), {
|
||||
"pm": handle_pm,
|
||||
"mode": handle_mode,
|
||||
|
|
|
@ -14,6 +14,7 @@ class Bot:
|
|||
|
||||
self.settings = dict()
|
||||
self.places = list()
|
||||
self.tasks = None
|
||||
self.author = ""
|
||||
|
||||
self.recv_size = 2048
|
||||
|
@ -195,6 +196,10 @@ class Bot:
|
|||
|
||||
print("DEBUG: Joined")
|
||||
|
||||
if self.tasks is not None:
|
||||
if getattr(self.tasks, "run", None) is not None:
|
||||
self.tasks.run()
|
||||
|
||||
while self.running:
|
||||
message = self.ircsock.recv(self.recv_size).decode()
|
||||
message = message.strip(self.splitter)
|
||||
|
|
38
bot/tasks.py
38
bot/tasks.py
|
@ -1,3 +1,37 @@
|
|||
import time
|
||||
import sched
|
||||
from threading import Thread
|
||||
|
||||
class Tasks:
|
||||
def __init__(self):
|
||||
pass
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.scheduler = sched.scheduler(time.time, time.sleep)
|
||||
self.thread = Thread(target=self.worker, args=(self,))
|
||||
self.coroutines = list()
|
||||
self.states = dict()
|
||||
|
||||
def periodic(self, scheduler, interval, action, index, state=dict()):
|
||||
self.states[index] = action(state)
|
||||
scheduler.enter(interval, 1, self.periodic, (
|
||||
scheduler, interval, action, index, self.states[index]
|
||||
))
|
||||
|
||||
def worker(self, tasks):
|
||||
for c, coro in enumerate(tasks.coroutines):
|
||||
interval = coro["interval"]
|
||||
worker = coro["worker"]
|
||||
state = coro.get("state", dict())
|
||||
state["bot"] = tasks.bot
|
||||
tasks.periodic(tasks.scheduler, interval, worker, c, state)
|
||||
tasks.scheduler.run()
|
||||
|
||||
def add_coroutine(self, worker, interval, state=dict()):
|
||||
self.coroutines.append({
|
||||
"worker": worker,
|
||||
"interval": interval,
|
||||
"state": state
|
||||
})
|
||||
|
||||
def run(self):
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
|
@ -0,0 +1,19 @@
|
|||
from coroutines.bbj import BBJ
|
||||
|
||||
# {
|
||||
# "worker": test,
|
||||
# "interval": 3
|
||||
# }
|
||||
# def test(bot):
|
||||
# print("Testing {}".format(bot.botnick))
|
||||
|
||||
coroutines = [
|
||||
{
|
||||
"worker": lambda state: BBJ(state).start(),
|
||||
"interval": 5,
|
||||
"state": {
|
||||
"source": "http://localhost:7099/api",
|
||||
"channels": ["#insane"], #team
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,88 @@
|
|||
from urllib.request import Request, urlopen
|
||||
from urllib.parse import urlencode
|
||||
from urllib.error import HTTPError
|
||||
from datetime import datetime
|
||||
from json import loads, dumps
|
||||
from re import sub
|
||||
|
||||
class BBJ:
|
||||
def __init__(self, state):
|
||||
self.name = "bbj"
|
||||
self.bot = state["bot"]
|
||||
self.source = state["source"]
|
||||
self.channels = state["channels"]
|
||||
self.memory = state.get("memory", {
|
||||
"initialized": False,
|
||||
# "timestamp": datetime.now().timestamp(),
|
||||
"known": dict()
|
||||
})
|
||||
|
||||
def start(self):
|
||||
if not self.memory["initialized"]:
|
||||
self.memory["initialized"] = True
|
||||
self.fetch(self.cache)
|
||||
return self.run()
|
||||
|
||||
def run(self):
|
||||
self.fetch(self.mirror)
|
||||
return {
|
||||
"bot": self.bot,
|
||||
"source": self.source,
|
||||
"channels": self.channels,
|
||||
"memory": self.memory
|
||||
}
|
||||
|
||||
def cache(self, item):
|
||||
self.memory["known"][item["thread_id"]] = item["last_mod"]
|
||||
|
||||
def process_thread(self, thread_id, thread):
|
||||
data = thread.get("data", dict())
|
||||
title = data.get("title", "")
|
||||
replies = data.get("reply_count", "")
|
||||
messages = data.get("messages", "")
|
||||
usermap = thread.get("usermap", dict())
|
||||
reply = messages[replies]
|
||||
author = reply.get("author", "")
|
||||
username = usermap[author].get("user_name", "")
|
||||
body = reply.get("body", "")
|
||||
body = sub(r">>\d\n\n", r"", body)
|
||||
body = sub(r"\n", r" ", body)
|
||||
php = "https://bbj.tilde.team/index.php"
|
||||
link = "{}?thread_id={}".format(php, thread_id)
|
||||
for channel in self.channels:
|
||||
response = "'{}' ({}) : {} <{}>".format(title, username, body, link)
|
||||
message = "[{}] {}".format(self.name, response)
|
||||
self.bot.send_message(channel, message)
|
||||
|
||||
def get_thread(self, thread_id, callback):
|
||||
params = {
|
||||
"thread_id": thread_id
|
||||
}
|
||||
post_params = str(dumps(params)).encode()
|
||||
thread_load = Request("{}/thread_load".format(self.source), post_params)
|
||||
thread_load.add_header("Content-Type", "application/json")
|
||||
|
||||
try:
|
||||
response = callback(thread_id, loads(urlopen(thread_load).read()))
|
||||
except HTTPError:
|
||||
return
|
||||
|
||||
def mirror(self, item):
|
||||
thread_id = item["thread_id"]
|
||||
last_mod = self.memory["known"][thread_id]
|
||||
if last_mod == item["last_mod"]:
|
||||
return
|
||||
|
||||
self.memory["known"][thread_id] = item["last_mod"]
|
||||
self.get_thread(thread_id, self.process_thread)
|
||||
|
||||
def fetch(self, callback):
|
||||
thread_index = Request("{}/thread_index".format(self.source))
|
||||
|
||||
try:
|
||||
response = loads(urlopen(thread_index).read())
|
||||
threads = response.get("data", dict())
|
||||
for thread in threads:
|
||||
callback(thread)
|
||||
except HTTPError:
|
||||
return
|
Loading…
Reference in New Issue