2020-11-15 15:53:28 +01:00
#!/bin/env python3
2021-08-31 14:59:16 +02:00
# SPDX-License-Identifier: MIT
2020-11-17 18:15:06 +01:00
import asyncio , configparser
2020-11-15 15:53:28 +01:00
from irctokens import build , Line
from ircrobots import Bot as BaseBot
from ircrobots import Server as BaseServer
from ircrobots import ConnectionParams
2021-07-11 19:44:45 +02:00
import pickle
2022-01-20 19:48:29 +01:00
import json
2020-11-15 15:53:28 +01:00
2020-11-17 18:15:06 +01:00
servers = [ ]
match_players = { }
2020-11-24 19:29:56 +01:00
connections = { }
2022-01-20 19:48:29 +01:00
admins = { }
2020-11-15 15:53:28 +01:00
2020-11-16 02:35:34 +01:00
def update_file ( name ) :
2021-07-11 19:44:45 +02:00
with open ( f " playerlist- { name } .txt " , " wb " ) as file :
pickle . dump ( match_players , file )
2020-11-15 15:53:28 +01:00
2020-11-17 18:15:06 +01:00
def read_file ( name ) :
2021-07-11 19:44:45 +02:00
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 " )
2020-11-15 15:53:28 +01:00
class Server ( BaseServer ) :
async def line_read ( self , line : Line ) :
2021-07-12 12:34:50 +02:00
print ( " Line Params: " , line . params )
2020-11-17 18:15:06 +01:00
if " PRIVMSG " in line . command and any ( channel in line . params [ 0 ] for channel in self . params . autojoin ) :
2021-07-12 18:01:32 +02:00
chan = self . channels [ line . params [ 0 ] . lstrip ( " @ " ) ] . name
2021-07-12 12:34:50 +02:00
if line . params [ 1 ] . startswith ( " .match " ) :
2021-07-12 18:01:32 +02:00
channel = self . channels [ line . params [ 0 ] . lstrip ( " @ " ) ]
2021-07-11 19:44:45 +02:00
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 = " "
if game not in match_players [ self . name + ' - ' + chan ] :
await self . send ( build ( " PRIVMSG " , [ chan , " ERROR: no players in " + game ] ) )
else :
for player in match_players [ self . name + ' - ' + chan ] [ game ] :
pfold = self . casefold ( player )
if pfold in channel . users :
ping + = f " { channel . users [ pfold ] . nickname } "
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 " ] ) )
2020-11-15 15:53:28 +01:00
2021-07-12 12:34:50 +02:00
elif line . params [ 1 ] . startswith ( " .add " ) :
2020-11-16 02:35:34 +01:00
user = line . source . split ( ' ! ' ) [ 0 ]
2021-07-11 19:44:45 +02:00
if len ( line . params [ 1 ] . split ( " " ) ) < 2 :
await self . send ( build ( " PRIVMSG " , [ chan , " ERROR: game not specified " ] ) )
2020-11-15 15:53:28 +01:00
else :
2021-07-11 19:44:45 +02:00
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. " ] ) )
2020-11-15 15:53:28 +01:00
2021-07-12 12:34:50 +02:00
elif line . params [ 1 ] . startswith ( " .list " ) :
user = line . source . split ( ' ! ' ) [ 0 ]
if len ( line . params [ 1 ] . split ( " " ) ) < 2 :
2021-08-31 15:33:51 +02:00
games = sorted ( match_players [ self . name + ' - ' + chan ] . keys ( ) )
while len ( games ) :
await self . send ( build ( " PRIVMSG " , [ chan , " list: " + ' , ' . join ( games [ : 20 ] ) ] ) )
del games [ : 20 ]
2021-07-12 12:34:50 +02:00
else :
game = " " . join ( line . params [ 1 ] . split ( " " ) [ 1 : ] ) . lower ( )
if game not in match_players [ self . name + ' - ' + chan ] :
2021-07-13 22:47:08 +02:00
await self . send ( build ( " PRIVMSG " , [ chan , " ERROR: no players in " + game + " list. " ] ) )
2021-07-12 12:34:50 +02:00
else :
2021-07-13 22:47:08 +02:00
await self . send ( build ( " PRIVMSG " , [ chan , game + " players: " + str ( [ ' _ ' + e for e in match_players [ self . name + ' - ' + chan ] [ game ] ] ) ] ) )
2022-01-20 19:48:29 +01:00
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 :
2021-08-31 15:33:51 +02:00
2022-01-20 19:48:29 +01:00
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 ]
2022-01-20 20:03:05 +01:00
update_file ( self . name + ' - ' + chan )
2022-01-20 19:48:29 +01:00
await self . send ( build ( " PRIVMSG " , [ chan , " Removed " + game ] ) )
2021-07-12 12:34:50 +02:00
elif line . params [ 1 ] . startswith ( " .del " ) :
2020-11-15 15:53:28 +01:00
user = line . source . split ( ' ! ' ) [ 0 ]
2021-07-11 19:44:45 +02:00
if len ( line . params [ 1 ] . split ( " " ) ) < 2 :
await self . send ( build ( " PRIVMSG " , [ chan , " ERROR: game not specified " ] ) )
2020-11-15 15:53:28 +01:00
else :
2021-07-11 19:44:45 +02:00
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. " ] ) )
2020-11-15 15:53:28 +01:00
elif line . params [ 1 ] . startswith ( " .help " ) :
2021-07-12 22:44:01 +02:00
await self . send ( build ( " PRIVMSG " , [ chan , " .add game: Add to list; .del game: Remove from list; .match game: Ping everyone on list; .list game: list people added to the game; .list: list games " ] ) )
2020-11-15 15:53:28 +01:00
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 ( ) :
2020-11-17 18:15:06 +01:00
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 } . " )
2020-11-24 18:14:29 +01:00
exit ( 1 )
2022-01-20 19:48:29 +01:00
elif not config [ section ] [ ' admins ' ] :
print ( f " ERROR: You didn ' t define any admins in section { section } . " )
exit ( 1 )
2020-11-17 18:15:06 +01:00
server = config [ section ] [ ' server ' ]
nickname = config [ section ] [ ' nickname ' ]
2020-11-24 19:29:56 +01:00
channels = set ( config [ section ] [ ' channels ' ] . split ( ) )
2022-01-20 19:48:29 +01:00
try :
admins [ section ] = json . loads ( config [ section ] [ ' admins ' ] )
except Exception as e :
print ( f " ERROR: Invalid admins in section { section } . " )
print ( e )
exit ( 1 )
2020-11-24 19:29:56 +01:00
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 ] } )
2020-11-17 18:15:06 +01:00
servers . append ( { ' name ' : section , ' opts ' : { ' server ' : server , ' nickname ' : nickname , ' channels ' : channels } } )
# read_file()
2020-11-15 15:53:28 +01:00
bot = Bot ( )
2020-11-17 18:15:06 +01:00
for entry in servers :
name = entry [ ' name ' ]
server = entry [ ' opts ' ] [ ' server ' ]
botnick = entry [ ' opts ' ] [ ' nickname ' ]
channels = entry [ ' opts ' ] [ ' channels ' ]
params = ConnectionParams ( botnick , server , 6697 , True )
for channel in channels :
params . autojoin . append ( channel )
2021-07-11 19:44:45 +02:00
print ( " Reading channel " , channel )
2020-11-17 18:15:06 +01:00
read_file ( name + ' - ' + channel )
2021-07-11 19:44:45 +02:00
print ( match_players )
2020-11-15 15:53:28 +01:00
await bot . add_server ( name , params )
2021-07-11 19:44:45 +02:00
print ( " Match players is: " , match_players )
2020-11-15 15:53:28 +01:00
await bot . run ( )
if __name__ == " __main__ " :
asyncio . run ( main ( ) )