You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
8.3 KiB
Python

import sys, os
import pydle
import asyncio
import arrow
from supportbot.reddit import Reddit
from supportbot.db import SupportRequest, IRCSupportOperator
from supportbot import config
class IRCBot(pydle.Client):
async def on_connect(self):
for room in config.ROOMS:
await self.join(room)
while True:
print("Checking reddit for new posts")
r = Reddit()
new_requests = []
subreddit = r.reddit.subreddit(r.subreddit)
# Check for new submissions
for submission in subreddit.new():
if not SupportRequest.select().where(SupportRequest.post_id == submission.id):
s = SupportRequest(
post_id=submission.id,
author=submission.author,
title=submission.title,
permalink=submission.permalink,
timestamp=submission.created_utc
)
s.save()
print(f"Added Reddit post {submission.id} as record {s.id}")
new_requests.append(s)
# Only post the totals into IRC
if new_requests:
await self.message(room, f"Found {len(new_requests)} new Reddit posts in /r/monerosupport. Use `.list` to see the list and `.request x` to see each one.")
# Check stored posts to see if they're solved
posts = SupportRequest.select().where(SupportRequest.solved == False)
for post in posts:
p = r.reddit.submission(post.post_id)
if p.link_flair_text:
print(f"Marking post {post.id} ({post.post_id}) as solved")
post.solved = True
post.save()
# Add configured admins as admins
for nick in config.ADMIN_NICKNAMES:
if not IRCSupportOperator.select().where(IRCSupportOperator.irc_nick == nick):
print(f"Adding {nick} as an admin")
i = IRCSupportOperator(
irc_nick=nick,
is_a_regular=True,
is_support_admin=True,
)
i.save()
await asyncio.sleep(120)
async def on_message(self, target, source, message):
if source == self.nickname:
return
else:
print(f"Target: {target} - Source: {source} - Message: {message}")
if self.nickname in message:
await self.message(target, f"Sup. I'm not very helpful yet, but getting there. Try `.help`")
# list command to show series of unsolved/active support requests
if message in [".list"]:
s = []
reqs = SupportRequest.select().where(
SupportRequest.solved==False
).order_by(SupportRequest.timestamp)
for req in reqs:
s.append(f"{req.id}")
await self.message(target, ", ".join(s))
# request command to view meta about a specific support request
if message.startswith(".request ") or message in [".request"]:
msg = message.split()
if not len(msg) > 1:
await self.message(target, "Invalid arguments")
return
try:
post_id = int(msg[1])
except:
await self.message(target, "Invalid arguments")
return
req = SupportRequest.select().where(
SupportRequest.id==post_id
).first()
if req:
if req.assigned:
_a = f"ASSIGNED ({req.assignee.irc_nick})"
else:
_a = "UNASSIGNED"
if req.solved:
_s = "SOLVED"
else:
_s = "UNSOLVED"
await self.message(target, f"{req.id}: {req.title} - {arrow.get(req.timestamp).humanize()} - https://reddit.com{req.permalink} - {_a} - {_s}")
else:
await self.message(target, "No record with that ID")
# claim support ticket - you become the assignee/helpers
if message.startswith(".claim ") or message in [".claim"]:
msg = message.split()
if not len(msg) > 1:
await self.message(target, "Invalid arguments")
return
try:
post_id = int(msg[1])
except:
await self.message(target, "Invalid arguments")
return
req = SupportRequest.select().where(
SupportRequest.id == post_id
).first()
if req:
if not await self.is_registered(source):
i = IRCSupportOperator(irc_nick=source)
i.save()
else:
i = IRCSupportOperator.select().where(IRCSupportOperator.irc_nick == source)
req.assigned = True
req.assignee = i
req.save()
await self.message(target, f"Support request {req.id} claimed by {source}")
else:
await self.message(target, "No record with that ID")
# queue command only shows things assigned to you
if message in [".queue"]:
user = IRCSupportOperator.select().where(IRCSupportOperator.irc_nick == source)
if not user:
await self.message(target, "You don't have a queue.")
return
reqs = SupportRequest.select().where(
SupportRequest.assignee == user,
SupportRequest.solved == False
)
if reqs:
await self.message(target, ", ".join(reqs))
else:
await self.message(target, "No support requests assigned to you.")
if message.startswith(".promote ") or message in [".promote"]:
msg = message.split()
if not len(msg) > 1:
await self.message(target, "Invalid arguments.")
return
promoted_nick = str(msg[1])
if not await self.is_admin(source):
await self.message(target, "You are not an admin of the support bot.")
return
if IRCSupportOperator.select().where(IRCSupportOperator.irc_nick == promoted_nick):
await self.message(target, "User already exists!")
return
i = IRCSupportOperator(
irc_nick=promoted_nick,
is_support_admin=True,
is_a_regular=True
)
i.save()
await self.message(target, "Added IRC support user:", irc_nick)
# help command shows available commands
if message in [".help"]:
await self.message(target, "`.list`: Show open support tickets on Reddit and synchronized to the database. | `.request x`: Show metadata of support request \"x\". | `.claim x`: Claim support request \"x\" | `.queue`: Show support requests assigned to you | `.promote x`: Allow user \"x\" to manage more support duties")
async def is_admin(self, nickname):
admin = False
if nickname in config.ADMIN_NICKNAMES:
info = await self.whois(nickname)
admin = info['identified']
print("info: ", info)
return admin
async def is_support_admin(self, nickname):
if IRCSupportOperator.select().where(IRCSupportOperator.is_support_admin == True):
return True
else:
return False
async def is_registered(self, nickname):
irc_nick = IRCSupportOperator.select().where(
IRCSupportOperator.irc_nick==nickname
).first()
if irc_nick:
return True
else:
return False
def run_bot():
try:
print(f"[+] Starting IRC bot connecting to {config.IRC_HOST}...\n")
client = IRCBot(nickname=config.BOT_NICKNAME)
client.run(config.IRC_HOST, tls=True, tls_verify=False)
except KeyboardInterrupt:
print(' - Adios')
try:
sys.exit(0)
except SystemExit:
os._exit(0)