-
Notifications
You must be signed in to change notification settings - Fork 0
/
chatcraft.py
executable file
·181 lines (150 loc) · 6.87 KB
/
chatcraft.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
from cmath import log
from hashlib import new
import time
import discord
import io
import os
import threading
import json
import asyncio
import emoji
import logging
import sys
client = discord.Client()
client_loop = client.loop
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(name)s] [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler("latest.log"),
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
keywords_death = {"shot", "pummeled", "death", "escape",
"drowned", "up", "killed", "hit", "fell", "squashed",
"flames", "walked", "fighting", "went", "swim", "lightning",
"lava", "slain", "fireballed", "suffocated", "squished",
"impaled", "live", "withered", "died" "obliterated",
"sonically-charged", "crisp", "skewered", "froze", "bang"}
prev_file_length = 0
def between_listener(channel):
new_loop = asyncio.new_event_loop()
new_loop.run_until_complete(minecraft_messages_listener(channel))
new_loop.close()
def load_uuids():
with open('./UUID.json', 'r') as f:
uuids = json.load(f)
return uuids
def save_uuids(uuids):
with open('./UUID.json', 'w') as f:
json.dump(uuids, f, indent=4)
async def minecraft_messages_listener(channel):
logger = logging.getLogger(__name__)
path = logPath + "latest.log"
log_file = open(path, "r")
global prev_file_length
current_file_length = sum(1 for line in open(path))
for i in range(prev_file_length):
log_file.readline()
UUID = load_uuids()
logger.info("Listening to minecraft log %s", path)
minecraft_channel = client.get_channel(channel.id)
while 1:
try:
current_file_length = sum(1 for line in open(path))
server_log_file = open(path, 'r')
for i in range(prev_file_length):
server_log_file.readline()
for i in range(current_file_length - prev_file_length):
str = server_log_file.readline()
# Checks if server is up or down
if "[Server thread/INFO]: Done" in str and ")! For help, type \"help\"" in str:
logger.info("Detected server startup")
embedded = discord.Embed(title="Server is Up!", colour=discord.Colour.green(), type="rich")
handle_minecraft_message(minecraft_channel, embedded)
if "[Server thread/INFO]: Stopping server" in str:
logger.info("Detected server shutdown")
embedded = discord.Embed(title="Server is Down!", colour=discord.Colour.red(), type="rich")
handle_minecraft_message(minecraft_channel, embedded)
# Gets UUID of player
if "[User Authenticator #" in str and "/INFO]: UUID of player" in str:
split_str = str.split()
UUID[split_str[7]] = split_str[9]
save_uuids(UUID)
# Checks if server someone joined or left the game
if ("<" not in str and ">" not in str) and ("joined the game" in str or "left the game" in str):
split_str = str.split()
if "joined" in str:
embedded = discord.Embed(title=str[33:], colour=discord.Colour.green(), type="rich")
else:
embedded = discord.Embed(title=str[33:], colour=discord.Colour.greyple(), type="rich")
if split_str[3] in UUID.keys():
url = f'https://crafatar.com/avatars/{UUID[split_str[3]]}?size=24'
logger.info(url)
embedded.set_thumbnail(url=url)
handle_minecraft_message(minecraft_channel, embedded)
# Checks if player action
if "<Server>" not in str and "[Server thread/INFO]: /" not in str:
# Checks if player message
if "<" in str and ">" in str and "<null>" not in str:
str = str[33:]
handle_minecraft_message(minecraft_channel, str)
# Checks if player kill
elif "ServerLevel" not in str:
split_str = str.split()
check_death = set(split_str)
if len(check_death & keywords_death) >= 1:
embedded = discord.Embed(title=str[33:], colour=discord.Colour.red(), type="rich")
if split_str[3] in UUID.keys():
url = f'https://crafatar.com/avatars/{UUID[split_str[3]]}?size=24'
embedded.set_thumbnail(url=url)
handle_minecraft_message(minecraft_channel, embedded)
prev_file_length = current_file_length
server_log_file.close()
except:
continue
prev_file_length = current_file_length
asyncio.sleep(0.05)
log_file.close()
def handle_minecraft_message(minecraft_channel, str):
handle_minecraft_message = asyncio.run_coroutine_threadsafe(send_message(minecraft_channel, str), client_loop)
handle_minecraft_message.result()
async def send_message(channel, message):
if type(message) is discord.Embed:
logger.info("sending out embedded message %s", message)
await channel.send(embed=message)
else:
logger.info("sending out message %s", message)
await channel.send(message)
@client.event
async def on_ready():
logger.info('logged in as %s', client.user.name)
perm_channel = discord.TextChannel
logger.info("Listening to Channel %s", channel_name)
await client.change_presence(activity=discord.Game(name=ip))
for channel in client.get_all_channels():
if channel.name == channel_name:
perm_channel = channel
global prev_file_length
path = logPath + "latest.log"
prev_file_length = sum(1 for line in open(path))
loop = client.loop
x = threading.Thread(target=between_listener, args=(perm_channel,))
x.start()
@client.event
async def on_message(message):
if message.author == client.user or message.channel.name != channel_name:
return
# print(emoji.demojize(message.content))
if len(message.attachments) > 0:
message.content = message.content +": Uploaded Attachment"
command = f'screen -S mcserver -p 0 -X stuff "say <{message.author}> {emoji.demojize(message.content)} ^M"'
os.system(command)
f = open('config.json')
config = json.load(f)
channel_name = config['channel']
ip = config['ip']
logPath = config['logPath']
token = os.environ.get('DISCORD_TOKEN')
client.run(token)