210 lines
10 KiB
Python
Executable File
210 lines
10 KiB
Python
Executable File
#!/bin/env python3
|
|
# SPDX-License-Identifier: MIT
|
|
import asyncio, configparser
|
|
from irctokens import build, Line
|
|
from ircrobots import Bot as BaseBot
|
|
from ircrobots import Server as BaseServer
|
|
from ircrobots import ConnectionParams
|
|
import pickle
|
|
import json
|
|
|
|
servers = []
|
|
match_players = {}
|
|
connections = {}
|
|
admins = {}
|
|
lastPlayed = ""
|
|
|
|
def update_file(name):
|
|
with open(f"playerlist-{name}.txt", "wb") as file:
|
|
pickle.dump(match_players, file)
|
|
|
|
def read_file(name):
|
|
try:
|
|
with open(f"playerlist-{name}.txt", "rb") as file:
|
|
temp = pickle.load(file)
|
|
match_players[name] = temp[name]
|
|
except EOFError:
|
|
match_players[name] = {}
|
|
print("Empty")
|
|
|
|
|
|
class Server(BaseServer):
|
|
async def line_read(self, line: Line):
|
|
|
|
print("Line Params: ", line.params)
|
|
if "PRIVMSG" in line.command and any(channel in line.params[0] for channel in self.params.autojoin):
|
|
chan = self.channels[line.params[0].lstrip("@")].name
|
|
if line.params[1].startswith(".match"):
|
|
channel = self.channels[line.params[0].lstrip("@")]
|
|
if len(line.params[1].split(" ")) < 2:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: game not specified"]))
|
|
else:
|
|
game = " ".join(line.params[1].split(" ")[1:]).lower()
|
|
ping = ""
|
|
user = line.source.split('!')[0]
|
|
if game not in match_players[self.name + '-' + chan]:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: no players in "+ game]))
|
|
else:
|
|
matches = match_players[self.name + '-' + chan][game]
|
|
others = list(set(matches) - set([user])) # don't ping the user who .matched
|
|
global lastPlayed
|
|
lastPlayed = game
|
|
|
|
if len(others) > 0:
|
|
for player in others:
|
|
pfold = self.casefold(player)
|
|
if pfold in channel.users:
|
|
ping += f"{channel.users[pfold].nickname} "
|
|
else:
|
|
ping += f"{player} "
|
|
|
|
await self.send(build("PRIVMSG", [chan, "Anyone ready for " + game + f" : {ping} ?"]))
|
|
if connections[self.name]:
|
|
for connection,address in connections[self.name].items():
|
|
if connection in line.params[1]:
|
|
if ':' in address:
|
|
realaddress = address.split(':')[0]
|
|
port = address.split(':')[1]
|
|
self.send(build("PRIVMSG", [chan, f"Connect using nc {realaddress} {port}"]))
|
|
else:
|
|
self.send(build("PRIVMSG", [chan, f"Connect using nc {address} 1234"]))
|
|
else:
|
|
await self.send(build("PRIVMSG", [chan, user + ": you're the only one who plays this game :("]))
|
|
|
|
|
|
elif line.params[1].startswith(".add"):
|
|
user = line.source.split('!')[0]
|
|
if len(line.params[1].split(" ")) < 2:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: game not specified"]))
|
|
else:
|
|
game = " ".join(line.params[1].split(" ")[1:]).lower()
|
|
if game not in match_players[self.name + '-' + chan]:
|
|
match_players[self.name + '-' + chan][game] = set()
|
|
if user in match_players[self.name + '-' + chan][game]:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: player already in " + game + " list."]))
|
|
else:
|
|
match_players[self.name + '-' + chan][game].add(user)
|
|
update_file(self.name + '-' + chan)
|
|
await self.send(build("PRIVMSG", [chan, "Added " + user + " to the " + game + " match list."]))
|
|
|
|
elif line.params[1].startswith(".last"):
|
|
await self.send(build("PRIVMSG", [chan, "Last game played: " + lastPlayed]))
|
|
|
|
elif line.params[1].startswith(".list"):
|
|
user = line.source.split('!')[0]
|
|
if len(line.params[1].split(" ")) < 2:
|
|
games = sorted(match_players[self.name + '-' + chan].keys())
|
|
while len(games):
|
|
await self.send(build("PRIVMSG", [chan, "list: " + ', '.join(games[:20])]))
|
|
del games[:20]
|
|
else:
|
|
game = " ".join(line.params[1].split(" ")[1:]).lower()
|
|
if game not in match_players[self.name + '-' + chan]:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: no players in " + game + " list."]))
|
|
else:
|
|
await self.send(build("PRIVMSG", [chan, game + " players: " + str(['_' + e for e in match_players[self.name + '-' + chan][game]])]))
|
|
|
|
elif line.params[1].startswith(".remove"):
|
|
channel = self.channels[line.params[0].lstrip("@")].name
|
|
if channel in admins[self.name]:
|
|
fadmins = admins[self.name][channel]
|
|
else:
|
|
fadmins = []
|
|
user = line.source.split('!')[0]
|
|
game = " ".join(line.params[1].split(" ")[1:]).lower()
|
|
if game not in match_players[self.name + '-' + chan]:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: game " + game + " not found"]))
|
|
if user not in fadmins:
|
|
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: user " + user + " is not an admin"]))
|
|
if user in fadmins and game in match_players[self.name + '-' + chan]:
|
|
del match_players[self.name + '-' + chan][game]
|
|
update_file(self.name + '-' + chan)
|
|
await self.send(build("PRIVMSG", [chan, "Removed " + game]))
|
|
elif line.params[1].startswith(".del"):
|
|
user = line.source.split('!')[0]
|
|
if len(line.params[1].split(" ")) < 2:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: game not specified"]))
|
|
else:
|
|
game = " ".join(line.params[1].split(" ")[1:]).lower()
|
|
if game not in match_players[self.name + '-' + chan]:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: no players in "+ game]))
|
|
else:
|
|
if user not in match_players[self.name + '-' + chan][game]:
|
|
await self.send(build("PRIVMSG", [chan, "ERROR: player isn't in list."]))
|
|
else:
|
|
match_players[self.name + '-' + chan][game].remove(user)
|
|
if len(match_players[self.name + '-' + chan][game]) == 0:
|
|
del match_players[self.name + '-' + chan][game]
|
|
update_file(self.name + '-' + chan)
|
|
await self.send(build("PRIVMSG", [chan, "Removed " + user + " from the " + game + " match list."]))
|
|
|
|
elif line.params[1].startswith(".help"):
|
|
await self.send(build("PRIVMSG", [chan, " .add game: Add user to the game list; .del game: Remove user from the game list; .match game: Ping everyone on the game list; .list game: list people added to the game; .list: list games; .remove game: removes the game from the list (admin command); .last: show last played game"]))
|
|
|
|
async def line_send(self, line: Line):
|
|
print(f"{self.name} > {line.format()}")
|
|
|
|
class Bot(BaseBot):
|
|
def create_server(self, name: str):
|
|
return Server(self, name)
|
|
|
|
async def main():
|
|
config = configparser.ConfigParser()
|
|
with open('bot.ini', 'r') as configfile:
|
|
config.read_file(configfile)
|
|
for section in config.sections():
|
|
if not config[section]['server']:
|
|
print(f"ERROR: The section {section} on your bot.ini doesn't have a 'server' parameter.")
|
|
exit(1)
|
|
elif not config[section]['nickname']:
|
|
print(f"ERROR: The section {section} has no nickname defined.")
|
|
exit(1)
|
|
elif not config[section]['channels']:
|
|
print(f"ERROR: You didn't define any channels in section {section}.")
|
|
exit(1)
|
|
elif not config[section]['admins']:
|
|
print(f"ERROR: You didn't define any admins in section {section}.")
|
|
exit(1)
|
|
server = config[section]['server']
|
|
nickname = config[section]['nickname']
|
|
channels = set(config[section]['channels'].split())
|
|
try:
|
|
admins[section] = json.loads(config[section]['admins'])
|
|
except Exception as e:
|
|
print(f"ERROR: Invalid admins in section {section}.")
|
|
print(e)
|
|
exit(1)
|
|
|
|
if config[section]['connections']:
|
|
if len(config[section]['connections'].split()) % 2 != 0: # If connections isn't even
|
|
print(f"ERROR: The section {section} has an invalid 'connections' defined.")
|
|
exit(1)
|
|
config_connections = config[section]['connections'].split()
|
|
connections.update({section:{}})
|
|
for i in range(0, len(config_connections), 2):
|
|
connections[section].update({config_connections[i]:config_connections[i+1]})
|
|
|
|
servers.append({'name':section, 'opts':{'server':server, 'nickname':nickname, 'channels':channels}})
|
|
# read_file()
|
|
bot = Bot()
|
|
for entry in servers:
|
|
name = entry['name']
|
|
server = entry['opts']['server']
|
|
botnick = entry['opts']['nickname']
|
|
channels = entry['opts']['channels']
|
|
|
|
params = ConnectionParams(botnick, server, 6697)
|
|
for channel in channels:
|
|
params.autojoin.append(channel)
|
|
print("Reading channel", channel)
|
|
read_file(name + '-' + channel)
|
|
print(match_players)
|
|
await bot.add_server(name, params)
|
|
|
|
print("Match players is: ", match_players)
|
|
await bot.run()
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|