Skip to content

Commit 19550fb

Browse files
committed
Further refactoring and discord.py migration fixes for file transfers
1 parent 249a870 commit 19550fb

18 files changed

+300
-228
lines changed

chimera.py

+22-200
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,19 @@
11
# Basic Bot Dependencies
22
import discord
3-
import asyncio
43
from discord.ext.commands import Bot
54
import platform
65

7-
from dotenv import load_dotenv
6+
# Import configurations
7+
import configs
88

9-
# Used by !screenshot and !camera commands
10-
import configs as Configs
11-
12-
# Dependency of: lock, shutdown, sleep, hibernate, logoff, say, restart, screenshot
13-
import os
14-
15-
# Dependency of: lock, shutdown, sleep, hibernate, logoff, say, restart
16-
import time
17-
18-
# Dependency of screenshot
19-
from mss import mss
20-
21-
# Dependency of camera
22-
# from lib.camera_control import CameraControl #commented because of the workaround
23-
24-
# For using commands in different systems
25-
from lib.helpers import get_operating
26-
27-
# Dependency of media
28-
from lib.helpers import MediaControlAdapter
29-
30-
# Dependency of file
31-
from lib.filesystem_control import FileSystemControl
32-
import requests
33-
34-
# Dependency of log
35-
from datetime import datetime
36-
37-
# Module import
9+
# Modules import
3810
from modules import cmd_module, powershell_module, lock_module, sleep_module, shutdown_module, restart_module
11+
from modules import hibernate_module, logoff_module, screenshot_module, say_module, media_module, camera_module
12+
from modules import echo_module, log_module, file_module, helpme_module
3913

40-
# Load configuration parameters
41-
load_dotenv()
42-
43-
# Platform name
44-
operating_sys = get_operating()
4514

4615
# Here you can modify the bot's prefix and description and whether it sends help in direct messages or not.
47-
client = Bot(description="A remote administration bot for Discord", command_prefix=Configs.BOT_PREFIX, pm_help=False)
16+
client = Bot(description="A remote administration bot for Discord", command_prefix=configs.BOT_PREFIX)
4817

4918
from lib.helpers import Logger
5019

@@ -67,6 +36,7 @@ async def on_ready():
6736
print('--------')
6837
return await client.change_presence(activity=discord.Game(name='with your PC'))
6938

39+
7040
# Module: cmd
7141
# Description: Executes cmd command
7242
# Usage: !cmd "command"
@@ -75,6 +45,7 @@ async def on_ready():
7545
async def cmd(ctx, cmnd):
7646
await cmd_module.cmd(ctx, cmnd)
7747

48+
7849
# Module: powershell
7950
# Description: Executes powershell command
8051
# Usage: !powershell "command"
@@ -123,52 +94,28 @@ async def restart(ctx, seconds=0):
12394
# Module: hibernate
12495
# Description: Hibernates the system
12596
# Usage: !hibernate or !hibernate secondsToHibernation
126-
# Dependencies: time, os
12797
@client.command()
12898
@Logger(client)
12999
async def hibernate(ctx, seconds=0):
130-
await ctx.send("Hibernating system.")
131-
if operating_sys == "Windows":
132-
if time != 0:
133-
time.sleep(seconds)
134-
os.system("rundll32.exe PowrProf.dll,SetSuspendState")
135-
else:
136-
await ctx.send("Can't hibernate system.")
137-
await asyncio.sleep(3)
100+
await hibernate_module.hibernate(ctx, seconds)
138101

139102

140103
# Module: logoff
141104
# Description: Logs the user out of the system
142105
# Usage: !logoff or !logoff secondsToLogoff
143-
# Dependencies: time, os
144106
@client.command()
145107
@Logger(client)
146108
async def logoff(ctx, seconds=0):
147-
await ctx.send("Logging out of system.")
148-
if operating_sys == "Windows":
149-
if time != 0:
150-
time.sleep(seconds)
151-
os.system("Shutdown.exe -l")
152-
else:
153-
await ctx.send("Can't logoff system.")
154-
await asyncio.sleep(3)
109+
await logoff_module.logoff(ctx, seconds)
155110

156111

157112
# Module: screenshot
158113
# Description: Takes a screenshot and sends it back
159114
# Usage: !screenshot or !screenshot secondsToScreenshot
160-
# Dependencies: time, os, mss
161115
@client.command()
162116
@Logger(client)
163117
async def screenshot(ctx, seconds=0):
164-
if os.path.isfile('screenshot.png'): # Check if a screenshot.png exists, if yes, delete it so it can be replaced
165-
os.remove('screenshot.png')
166-
await ctx.send("Taking a screenshot.")
167-
if time != 0:
168-
time.sleep(seconds)
169-
with mss() as sct:
170-
filename = sct.shot(mon=-1, output='screenshot.png')
171-
await ctx.send_file(ctx.message.channel, 'screenshot.png')
118+
await screenshot_module.screenshot(ctx, seconds)
172119

173120

174121
# Module: say
@@ -178,187 +125,62 @@ async def screenshot(ctx, seconds=0):
178125
@client.command()
179126
@Logger(client)
180127
async def say(ctx, txt):
181-
if operating_sys == "Windows":
182-
await ctx.send("Saying: " + txt)
183-
os.system(
184-
"powershell Add-Type -AssemblyName System.Speech; $synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer; $synth.Speak('" + txt + "')")
185-
elif operating_sys == "Linux":
186-
await ctx.send("Saying: " + txt)
187-
os.system('spd-say "{}"'.format(txt))
188-
else:
189-
await ctx.send("Can't use TTS")
190-
await asyncio.sleep(3)
128+
await say_module.say(ctx, txt)
191129

192130

193131
# Module: media
194132
# Description: Controls Media Features
195133
# Usage: !media command or !media command times
196-
# Dependencies: pynput, time, helpers
197134
@client.command()
198135
@Logger(client)
199136
async def media(ctx, command, times=1):
200-
media_control = MediaControlAdapter(operating_sys)
201-
switcher = {
202-
'vol-up': media_control.up_volume,
203-
'vol-down': media_control.down_volume,
204-
'vol-mute': media_control.mute_volume,
205-
'next': media_control.media_next,
206-
'prev': media_control.media_previous,
207-
'stop': media_control.media_stop,
208-
'play': media_control.media_play_pause,
209-
'pause': media_control.media_play_pause
210-
}
211-
212-
for time in range(0, times):
213-
switcher[command]()
214-
await asyncio.sleep(0.5)
215-
216-
await ctx.send('Media Adjusted!')
137+
await media_module.media(ctx, command, times)
217138

218139

219140
# Module: camera
220141
# Description: Records a video or takes a photo (no audio)
221142
# Usage: !camera command time
222-
# Dependencies: cv2, datetime, timedelta
223143
@client.command()
224144
@Logger(client)
225145
async def camera(ctx, command, time=5):
226-
await ctx.send('Recording!')
227-
python_alias = Configs.PYTHON_ALIAS
228-
229-
if command == 'photo':
230-
# CameraControl.photo_capture()
231-
os.system("{} lib/camera_control.py photo".format(python_alias)) # workaround
232-
await ctx.send_file(ctx.message.channel, 'photo.jpg')
233-
234-
if command == 'video':
235-
# await CameraControl.video_capture(time=time)
236-
os.system("{} lib/camera_control.py video {}".format(python_alias, time)) # workaround
237-
await ctx.send_file(ctx.message.channel, 'video.avi')
146+
await camera_module.camera(ctx, command, time)
238147

239148

240149
# Module: echo
241150
# Description: Turns command output display to discord chat on and off (works for !cmd and !powershell)
242151
# Usage: !echo off or !echo on
243-
# Dependencies: None
244152
@client.command()
245153
@Logger(client)
246154
async def echo(ctx, status):
247-
if status == "on":
248-
Configs.initial_display_output = True
249-
await ctx.send("!cmd and !powershell output will be displayed in chat. ")
250-
elif status == "off":
251-
Configs.initial_display_output = False
252-
await ctx.send("!cmd and !powershell output will be hidden from chat. ")
253-
else:
254-
await ctx.send("Parameter of echo can be off or on. ")
155+
await echo_module.echo(ctx, status)
255156

256157

257158
# Module: log
258159
# Description: Turns on of off logs in chat. Also can be used to retrieve Chimera execution logs
259160
# Usage: !log [off|on] | [show] [date (format: YYYY-MM-DD)]
260-
# Dependencies: logging, datetime
261161
@client.command()
262162
@Logger(client)
263163
async def log(ctx, param, date=None):
264-
if param == "on":
265-
Configs.discord_logs_enabled = True
266-
await ctx.send("Exceptions log will now be displayed in chat.")
267-
elif param == "off":
268-
Configs.discord_logs_enabled = False
269-
await ctx.send("Running on silent mode now.")
270-
elif param == "show":
271-
date = date if date else (datetime.now()).strftime('%Y-%m-%d')
272-
await ctx.send_file(ctx.message.channel, '{}/{}.txt'.format(Logger.DIRECTORY, date))
273-
else:
274-
await ctx.send("Parameter of !log can be off or on. ")
164+
await log_module.log(ctx, param, date)
275165

276166

277167
# Module: file
278168
# Description: Allows file download, upload and system navigation
279169
# Usage: !file [command] [[path]|[times]]
280-
# Dependencies: filesystem_control, requests
281170
@client.command()
282171
@Logger(client)
283172
async def file(ctx, command, *args):
284-
filesystem_control = FileSystemControl(Configs.initial_path)
285-
await filesystem_control.load_path_from_memory()
286-
287-
async def set_absolute_path(path):
288-
new_path = await filesystem_control.set_path(path, False)
289-
return 'Current location set to {}'.format(new_path)
290-
291-
async def set_relative_path(path):
292-
new_path = await filesystem_control.set_path(path, True)
293-
return 'Current location set to {}'.format(new_path)
294-
295-
async def retrive_file(path=None):
296-
file_path = await filesystem_control.retrieve_file(path)
297-
await ctx.send_file(ctx.message.channel, file_path)
298-
299-
async def save_file(path=None):
300-
filename = ctx.message.attachments[0]['filename']
301-
url = ctx.message.attachments[0]['url']
302-
303-
r = requests.get(url, allow_redirects=True)
304-
if r.status_code / 100 != 2:
305-
raise Exception('Download request from Discord returned {}'.r.status_code)
306-
file = r.content
307-
308-
file_path = await filesystem_control.save_file(file, filename, path)
309-
return 'File Saved on {}'.format(file_path)
310-
311-
async def list_directory():
312-
dir_list = await filesystem_control.list_directory()
313-
result = "Directory items:\n"
314-
for item in dir_list:
315-
result += "`{}`\n".format(item.name)
316-
return result
317-
318-
switcher = {
319-
'absolute': set_absolute_path,
320-
'relative': set_relative_path,
321-
'list': list_directory,
322-
'retrieve': retrive_file,
323-
'save': save_file
324-
}
325-
326-
if len(args) > 0:
327-
message = await switcher[command](*args)
328-
else:
329-
message = await switcher[command]()
330-
if message: await ctx.send(message)
173+
await file_module.file(ctx, command, *args)
331174

332175

333-
# Module: file
176+
# Module: helpme
334177
# Description: Allows file download, upload and system navigation
335-
# Usage: !file [command] [[path]|[times]]
336-
# Dependencies: filesystem_control, requests
178+
# Usage: !file [command]
337179
@client.command()
338180
@Logger(client)
339181
async def helpme(ctx, command=None):
340-
readme = open('readme.md', 'r')
341-
readme = readme.read()
342-
readme = readme.split('## ')
343-
344-
if command:
345-
features = [x for x in readme if x.split('\n', 1)[0] == 'Features Documentation:']
346-
features = features[0]
347-
348-
message = features
349-
350-
features = features.split('* ')
351-
feature = [x for x in features[1:] if x.replace("!", "").split(' ', 1)[0] == command]
352-
feature = feature[0]
353-
354-
message = "```{}```".format(feature)
355-
else:
356-
features = [x for x in readme if x.split('\n', 1)[0] == 'Features List:']
357-
features = features[0]
358-
359-
message = "```{}```".format(features)
360-
361-
await ctx.send(message)
182+
await helpme_module.helpme(ctx, command)
362183

363184

364-
client.run(Configs.BOT_TOKEN)
185+
# Application Entry Point
186+
client.run(configs.BOT_TOKEN)

configs.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
# Load configuration parameters
2+
from pathlib import Path
3+
from dotenv import load_dotenv
14
import os, lib.helpers
25

6+
env_path = Path('.') / '.env'
7+
load_dotenv(dotenv_path=env_path)
8+
39
BOT_TOKEN = os.getenv('DISCORD_BOT_TOKEN')
410

511
BOT_PREFIX = os.getenv('DISCORD_BOT_PREFIX', '!')
@@ -16,4 +22,4 @@
1622

1723
discord_logs_enabled = os.getenv('DISCORD_LOGS_ENABLED', False)
1824

19-
operating_sys = lib.helpers.get_operating()
25+
operating_sys = lib.helpers.get_operating()

modules/camera_module.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Module: camera
2+
# Description: Records a video or takes a photo (no audio)
3+
# Usage: !camera command time
4+
# Dependencies: cv2, datetime, timedelta
5+
6+
import os, asyncio, configs, discord
7+
8+
async def camera(ctx, command, time=5):
9+
await ctx.send('Recording!')
10+
python_alias = configs.PYTHON_ALIAS
11+
12+
if command == 'photo':
13+
# CameraControl.photo_capture()
14+
os.system("{} lib/camera_control.py photo".format(python_alias)) # workaround
15+
await ctx.send(file=discord.File('photo.jpg'))
16+
17+
if command == 'video':
18+
# await CameraControl.video_capture(time=time)
19+
os.system("{} lib/camera_control.py video {}".format(python_alias, time)) # workaround
20+
await ctx.send(file=discord.File('video.avi'))

modules/cmd_module.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
# Usage: !cmd "command"
44
# Dependencies: time, os
55

6-
import os, asyncio
7-
import configs as Configs
6+
import os, asyncio, configs
7+
88

99
async def cmd(ctx, cmnd):
1010
await ctx.send("Executing in command prompt: " + cmnd)
1111
cmnd_result = os.popen(cmnd).read()
12-
if Configs.initial_display_output:
12+
if configs.initial_display_output:
1313
await ctx.send(cmnd_result)
1414
await asyncio.sleep(3)

0 commit comments

Comments
 (0)