tcircv1/tcirc.py

277 lines
11 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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_mc_bot_v1'
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('IRC bot connected')
irc.connect((server, 6667))
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
elif m.group(1)=="\x02":
return "\xa7l" # bold
elif m.group(1)=="\x1d":
return "\xa7o" # italic
elif m.group(1)=="\x1f":
return "\xa7n" # underline
elif m.group(1)=="\x1e"
return "\xa7m" # strikethrough
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('mc_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 and ': [GriefPrevention] ' not in line:
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 + ' :' + line, 'utf8'))
elif 'left the game' in line and '[Server thread/INFO]: [Rcon] ' 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', 'logged off', 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 + ' :' + 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:
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 '@tildeverse:' not in line:
irc.send(bytes('PRIVMSG ' + channel + ' :' + line, 'utf8'))
elif any(' ' + death + ' ' in line for death in death_messages) and 'Villager EntityVillager[\'' not in line:
line = re.sub(r'^\[.*\]: ', '', line, 1)
print('sent ' + line)
irc.send(bytes('PRIVMSG ' + channel + ' :' + line, 'utf8'))
file.close()
def irc_to_mc():
print('started irc thread')
rcon = mcrcon.MCRcon()
rcon_password_file = open('rcon_password', 'r')
rcon_password = rcon_password_file.readline().strip()
rcon_password_file.close()
rcon.connect('0.0.0.0', 6668, 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'@tildeverse: ', 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("([\x02\x03\x0f\x1d\x1e\x1f])([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:
print("-- JOIN EVENT --")
print(text)
if 'PART' in text:
text = re.search(r':.*!', text).group(0)
text = text[:-1]
text = text[1:]
text = text + ' left irc'
if 'JOIN' in text:
text = re.search(r':.*!', text).group(0)
text = text[:-1]
text = text[1:]
text = text + ' joined irc'
rcon.command('say ' + text)
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)