275 lines
11 KiB
Python
Executable File
275 lines
11 KiB
Python
Executable File
#!/usr/bin/python3
|
||
# tcirc.py
|
||
# Copyright (C) 2018 oneseveneight
|
||
#
|
||
# This program is free software; you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation; either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License along
|
||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
#
|
||
# Email: oneseveneight@airmail.cc
|
||
|
||
import socket
|
||
import re
|
||
import mcrcon.mcrcon as mcrcon
|
||
import time
|
||
import threading
|
||
|
||
server = 'localhost'
|
||
channel ='#minecraft'
|
||
botnick = 'tildecraft_hardcore_bot_v1'
|
||
|
||
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||
print('IRC bot connected')
|
||
#irc.connect((server, 6667))
|
||
irc.connect((server, 2345))
|
||
print("connected")
|
||
irc.send(bytes('USER ' + botnick + ' '
|
||
+ botnick + ' ' + botnick
|
||
+ 'tcirc bot\n', 'utf8'))
|
||
irc.send(bytes('NICK ' + botnick + '\n', 'utf8'))
|
||
#irc.send(bytes('PRIVMSG nickserv :iNOOPE\r\n', 'utf8'))
|
||
time.sleep(5)
|
||
irc.send(bytes('JOIN ' + channel + '\n', 'utf8'))
|
||
|
||
irc_mc_color_mapping = {}
|
||
mc_irc_color_mapping = {}
|
||
def define_mapping(irc,mc):
|
||
global irc_mc_color_mapping, mc_irc_color_mapping
|
||
irc_mc_color_mapping[irc]=mc
|
||
mc_irc_color_mapping[mc]=irc
|
||
define_mapping(0,"f") # white
|
||
define_mapping(1,"0") # black
|
||
define_mapping(2,"1") # dark blue
|
||
define_mapping(3,"2") # dark green
|
||
define_mapping(4,"c") # light red
|
||
define_mapping(5,"4") # "brown" (dark red is closest)
|
||
define_mapping(6,"5") # purple
|
||
define_mapping(7,"6") # orange
|
||
define_mapping(8,"e") # yellow
|
||
define_mapping(9,"a") # green
|
||
define_mapping(10,"3") # dark aqua/cyan
|
||
define_mapping(11,"b") # aqua/cyan
|
||
define_mapping(12,"9") # light blue
|
||
define_mapping(13,"d") # pink (light purple is closest)
|
||
define_mapping(14,"8") # gray
|
||
define_mapping(15,"7") # light gray
|
||
|
||
def safeint(v):
|
||
try:
|
||
return int(v)
|
||
except:
|
||
return v
|
||
|
||
def irc_to_mc_colors(m):
|
||
if m.group(1)=="\x0f":
|
||
return "\xa7r" # reset
|
||
else:
|
||
return "\xa7"+irc_mc_color_mapping.get(safeint(m.group(2)),"f")
|
||
|
||
def mc_to_irc():
|
||
print('started mc thread')
|
||
death_messages_file = open('death_messages', 'r')
|
||
death_messages = death_messages_file.readlines()
|
||
death_messages_file.close()
|
||
death_messages = [s.replace('\n', '') for s in death_messages]
|
||
|
||
file = open('hc_remote_file')
|
||
file.readlines()
|
||
print('reading from file ' + file.name)
|
||
while 1:
|
||
time.sleep(1)
|
||
latest_lines = file.readlines()
|
||
for line in latest_lines:
|
||
if re.search('\[Async Chat Thread -.*?/INFO', line) is not None :
|
||
print('received ' + ''.join(line))
|
||
line = re.sub(r'', r'^[', line)
|
||
line = re.sub(r'\^.*?m', '', line)
|
||
line = re.sub(r'\^.*UUID', '', line)
|
||
line = re.sub(r'.*?Async Chat Thread.*?: ', '', line, 1)
|
||
line = re.sub(r' :', ':', line, 1)
|
||
print(line.split(' '))
|
||
print(line.split(' ')[-1])
|
||
if '[r]' in line.split(' ')[-1]:
|
||
line = re.sub(r'^.*?: ', '', line, 1)
|
||
line = re.sub(r'\[r\]', '', line, 1)
|
||
print('sent ' + line)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + line, 'utf8'))
|
||
if re.search(': (f|F)( |$)', line) is not None:
|
||
print('someone paid respects.')
|
||
fsgiven_file = open('fsgiven', 'r+')
|
||
fsgiven = fsgiven_file.readline().strip()
|
||
fsgiven = int(fsgiven) + 1
|
||
print(str(fsgiven) + ' total respects paid')
|
||
fsgiven_file.seek(0)
|
||
fsgiven_file.write(str(fsgiven))
|
||
fsgiven_file.truncate()
|
||
fsgiven_file.close()
|
||
response = 'Respects paid.'
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + response + '\n', 'utf8'))
|
||
|
||
elif '] logged in with entity id' in line:
|
||
print('received ' + ''.join(line))
|
||
line = re.sub(r'', r'^[', line)
|
||
line = re.sub(r'^\[.*?User Authenticator.*\n', '', line, 1, re.M)
|
||
line = re.sub(r'\[.*?: ', '', line, 1)
|
||
line = re.sub(r'\[/.*?\]', '', line, 1)
|
||
line = re.sub(r' with entity id.*', '', line, 1)
|
||
print('sent ' + line)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :[HARDCORE] ' + line, 'utf7'))
|
||
|
||
elif 'left the game' in line and 'IRC ' not in line:
|
||
print('received ' + ''.join(line))
|
||
line = re.sub(r'', r'^[', line)
|
||
line = re.sub(r'\[.*?: ', '', line, 1)
|
||
line = re.sub(r'left the game', 'left the HARDCORE game', line, 1)
|
||
line = re.sub(r'\[/.*?\]', '', line, 1)
|
||
line = re.sub(r'> ', '', line, 1)
|
||
line = re.sub(r'lost connection: Disconnected', 'disconnected', line, 1)
|
||
print('sent ' + line)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :[HARDCORE] ' + line, 'utf8'))
|
||
|
||
elif '[WEB]' in line:
|
||
print('received ' + ''.join(line))
|
||
line = re.sub(r'', r'^[', line)
|
||
line = re.sub(r'^.*?: ', '', line, 3)
|
||
line = re.sub(r'\^.*?m', '', line)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + line, 'utf8'))
|
||
print('sent ' + line)
|
||
#elif '> ' in line and '[LP] LOG' not in line:
|
||
elif '[Server thread/INFO]: [' in line and '[LP] LOG' not in line and ': [SavageDeathCompass] ' not in line and ': [GriefPrevention] ' not in line and '[Rcon]' not in line:
|
||
print('received ' + ''.join(line))
|
||
line = re.sub(r'', r'^[', line)
|
||
line = re.sub(r'^.*?: ', '', line, 3)
|
||
line = re.sub(r'\^.*?m', '', line)
|
||
line = re.sub(r'\[Rcon\].', r'', line)
|
||
print('sent ' + line)
|
||
if '@tilde.town:' not in line:
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + line, 'utf8'))
|
||
elif any(death in line for death in death_messages):
|
||
line = re.sub(r'^\[.*\]: ', '', line, 1)
|
||
print('sent ' + line)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + line, 'utf8'))
|
||
# the following applies to the hardcore server
|
||
elif '[Server thread/INFO]: <' in line:
|
||
if '@tilde.town:' not in line:
|
||
print('received ' + ''.join(line))
|
||
line = re.sub(r'', r'^[', line)
|
||
line = re.sub(r'^.*?: ', '', line, 3)
|
||
line = re.sub(r'\^.*?m', '', line)
|
||
line = re.sub(r'\[Rcon\].', r'', line)
|
||
print('sent ' + line)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :[HARDCORE] ' + line, 'utf8'))
|
||
|
||
file.close()
|
||
|
||
|
||
def irc_to_mc():
|
||
print('started irc thread')
|
||
rcon = mcrcon.MCRcon()
|
||
rcon_password_file = open('rcon_password_hc', 'r')
|
||
rcon_password = rcon_password_file.readline().strip()
|
||
rcon_password_file.close()
|
||
rcon.connect('mc.bhh.sh', 25575, rcon_password)
|
||
print('initiated rcon connection')
|
||
|
||
while 1:
|
||
time.sleep(1)
|
||
text = irc.recv(1024)
|
||
if len(text) == 0:
|
||
print('Disconnected, attempting to recconect')
|
||
irc.close()
|
||
irc.connect((server, 6667))
|
||
irc.send(bytes('USER ' + botnick + ' '
|
||
+ botnick + ' ' + botnick
|
||
+ 'tcirc bot\n', 'utf8'))
|
||
irc.send(bytes('NICK ' + botnick + '\n', 'utf8'))
|
||
time.sleep(5)
|
||
irc.send(bytes('PRIVMSG nickserv :iNOOPE\r\n', 'utf8'))
|
||
irc.send(bytes('JOIN ' + channel + '\n', 'utf8'))
|
||
print('IDENTIFIED')
|
||
text = irc.recv(1024)
|
||
text = text.decode('utf-8')
|
||
print('received ' + text)
|
||
|
||
if 'PRIVMSG ' + channel in text:
|
||
text = re.sub(r'\!.*?@', r'@', text, 1)
|
||
text = re.sub(r' PRIVMSG ' + channel, r'', text, 1)
|
||
text = re.sub(r' :', r':', text, 1)
|
||
text = re.sub(r':', r'', text, 1)
|
||
text = re.sub(r'@.*?:', r'@tilde.town: ', text, 1)
|
||
if '!uptime' in text:
|
||
print('seen uptime')
|
||
response = rcon.command('uptime')
|
||
response = response.split('\n')[0]
|
||
response = response.replace('\n', '')
|
||
response = re.sub('§.', '', response)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + response + '\n', 'utf8'))
|
||
print('PRIVMSG ' + channel + ' :' + response)
|
||
if '!online' in text:
|
||
print('seen online')
|
||
response = rcon.command('who')
|
||
response = response.replace('\n', '')
|
||
response = re.sub('§.', '', response)
|
||
response = re.sub(r'There are.*?: ', '', response, 1)
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + response + '\n', 'utf8'))
|
||
print('PRIVMSG ' + channel + ' :' + response)
|
||
elif '!fsgiven' in text:
|
||
print('fsgiven called')
|
||
fsgiven_file = open('fsgiven', 'r')
|
||
fsgiven = int(fsgiven_file.readline().strip())
|
||
fsgiven_file.close()
|
||
response = str(fsgiven) + ' fs given.'
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + response + '\n', 'utf8'))
|
||
else:
|
||
text = re.sub("([\x03\x0f])([0-9A-Fa-f]{1,2}(?:,[0-9A-Fa-f]{1,2})?)?",irc_to_mc_colors,text)
|
||
rcon.command('say ' + text[:-2])
|
||
if re.search(' (f|F) .*', text) is not None:
|
||
print('someone paid respects.')
|
||
fsgiven_file = open('fsgiven', 'r+')
|
||
fsgiven = fsgiven_file.readline().strip()
|
||
fsgiven = int(fsgiven) + 1
|
||
print(str(fsgiven) + ' total respects paid')
|
||
fsgiven_file.seek(0)
|
||
fsgiven_file.write(str(fsgiven))
|
||
fsgiven_file.truncate()
|
||
fsgiven_file.close()
|
||
response = 'Respects paid.'
|
||
irc.send(bytes('PRIVMSG ' + channel + ' :' + response + '\n', 'utf8'))
|
||
|
||
|
||
elif 'JOIN' in text or 'PART' in text:
|
||
text = re.sub(r':.*?\!', r'', text, 1)
|
||
text = re.sub(r'@localhost', r'', text, 1)
|
||
text = re.sub(r':WeeChat.*', r'', text, 1)
|
||
text = re.sub(r'JOIN', r'joined', text, 1)
|
||
text = re.sub(r'PART', r'left', text, 1)
|
||
rcon.command('say ' + text[:-2])
|
||
|
||
elif 'PING' in text:
|
||
print('pinged by server, returning pong')
|
||
irc.send(b'PONG ' + text.split()[1].encode() + b'\r\n')
|
||
print('sent PONG ' + text.split()[1] + '\r\n')
|
||
rcon.disconnect()
|
||
|
||
|
||
mc_thread = threading.Thread(target=mc_to_irc)
|
||
mc_thread.daemon = True
|
||
|
||
irc_thread = threading.Thread(target=irc_to_mc)
|
||
irc_thread.daemon = True
|
||
|
||
irc_thread.start()
|
||
mc_thread.start()
|
||
while 1:
|
||
time.sleep(1)
|