From f6cc27725634dde5c314889e1da3941692e30514 Mon Sep 17 00:00:00 2001 From: Arpit Choudhary Date: Thu, 3 Oct 2019 13:18:10 +0530 Subject: [PATCH] Windows Support (#561) * add battery * add ip * fix some spelling mistakes also closes #474 * timer and stopwatch working on win32 * add check ram for win32 * fix function names in shutdown.py lol, so many errors, what had i done * update README --- README.md | 25 ++++------ jarviscli/CmdInterpreter.py | 2 +- jarviscli/PluginManager.py | 2 +- jarviscli/plugins/battery.py | 25 +++++++++- jarviscli/plugins/clock.py | 6 +-- jarviscli/plugins/ip.py | 15 +++++- jarviscli/plugins/shutdown.py | 80 +++++++++++++++--------------- jarviscli/plugins/systemOptions.py | 19 +++++-- requirements.txt | 1 + 9 files changed, 109 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index a2bc36a53..3108ed4b7 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,15 @@ [![Build Status](https://travis-ci.org/sukeesh/Jarvis.svg?branch=master)](https://travis-ci.org/sukeesh/Jarvis) [![Join the chat at https://gitter.im/Sukeesh_Jarvis/Lobby](https://badges.gitter.im/Sukeesh_Jarvis/Lobby.svg)](https://gitter.im/Sukeesh_Jarvis/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -A Personal Assistant for Linux and MacOS +A Personal Assistant for Linux, MacOS and Windows ![Jarvis](http://i.imgur.com/xZ8x9ES.jpg) -Jarvis is a simple personal assistant for Linux and MacOS which works on the terminal. He can talk to you if you enable his voice. He can tell you the weather, he can find restaurants and other places near you. He can do some great stuff for you. Stay updated about [new functionalities](NEW_FUNCTIONALITIES.md). +Jarvis is a simple personal assistant for Linux, MacOS and Windows which works on the command line. He can talk to you if you enable his voice. He can tell you the weather, he can find restaurants and other places near you. He can do some great stuff for you. ## Getting Started -In order to start Jarvis just clone the repository and run `./setup.sh` +In order to start Jarvis just clone [this repository](https://github.com/sukeesh/Jarvis.git) and run `./setup.sh` Run **Jarvis** from anywhere by command `jarvis` @@ -18,8 +18,6 @@ On Mac OS X run `source setup.sh` On Windows run `setup.bat` -**NOTE: Jarvis is not fully ported to windows yet, and has only basic functionality. Jarvis's output is also a bit messy!** - You can start by typing `help` within the Jarvis command line to check what Jarvis can do for you. @@ -29,14 +27,14 @@ You can start by typing `help` within the Jarvis command line to check what Jarv ## Contributing -- PR's are accepted!! -- We follow PEP 8 guidelines. Before making a PR, make sure that your code is according to PEP8 standards. +- PRs are accepted!! +- We follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) guidelines. Before making a PR, make sure that your code is according to PEP 8 standards. - If you have some ideas for new features and you don't have time to implement them please open an issue with the tag new_feature - Please don't forget to comment (document) your code -### Quickstart: Create a new feature (plugin) +### QuickStart: Create a new feature (plugin) Create new file custom/hello_world.py @@ -68,7 +66,7 @@ jarvis is cool ### Creating a test -Creating a test is optionally but never a bad idea ;). +Creating a test is optional but never a bad idea ;). [Click here](doc/TESTING.md) to learn more about testing. @@ -81,9 +79,9 @@ Creating a test is optionally but never a bad idea ;). ## Optional Dependencies - Any pyttsx3 text-to-speech engine (``sapi5, nsss or espeak``) for Jarvis to talk out loud (e.g. Ubuntu do ``sudo apt install espeak``) -- Portaudio + python devel packages for voice control -- ``notify-send`` on Linux if you want to recive *nice* and deskotp-notification instead of *ugly* popup windows (e.g. Ubuntu do ``sudo apt install libnotify-bin``) -- ``ffmpeg`` if you want ``music`` to download songs as .mp3 instead .webm +- Portaudio + python-devel packages for voice control +- ``notify-send`` on Linux if you want to receive *nice* and desktop-notification instead of *ugly* pop up windows (e.g. Ubuntu do ``sudo apt install libnotify-bin``) +- ``ffmpeg`` if you want ``music`` to download songs as .mp3 instead of .webm ## Docker @@ -98,9 +96,8 @@ Run with docker (docker needs to be installed and running): **sukeesh** -See also the list of [contributors](https://github.com/sukeesh/Jarvis/graphs/contributors) who participated in this project. +See also the list of [contributors](https://github.com/sukeesh/Jarvis/graphs/contributors) who have participated in this project. ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details - diff --git a/jarviscli/CmdInterpreter.py b/jarviscli/CmdInterpreter.py index 743feb8a6..89659009c 100644 --- a/jarviscli/CmdInterpreter.py +++ b/jarviscli/CmdInterpreter.py @@ -349,7 +349,7 @@ def do_status(self, s): print_say( "{:<20}: {}".format( disabled, - "OR ".join(reason)), + " OR ".join(reason)), self) def help_status(self): diff --git a/jarviscli/PluginManager.py b/jarviscli/PluginManager.py index d266cb5e1..2abd4694f 100644 --- a/jarviscli/PluginManager.py +++ b/jarviscli/PluginManager.py @@ -220,7 +220,7 @@ def _plugin_get_requirements(self, requirements_iter): if key in plugin_requirements: plugin_requirements[key].extend(values) else: - warning("{}={}: No supportet requirement".format(key, values)) + warning("{}={}: No supported requirement".format(key, values)) return plugin_requirements diff --git a/jarviscli/plugins/battery.py b/jarviscli/plugins/battery.py index 32fc98cef..a0e715733 100644 --- a/jarviscli/plugins/battery.py +++ b/jarviscli/plugins/battery.py @@ -1,12 +1,33 @@ import subprocess -from plugin import plugin, require, LINUX +from plugin import plugin, require, LINUX, WINDOWS VALID_OPTIONS = ['status', 'vendor', 'energy', 'technology', 'remaining'] +@require(platform=WINDOWS) +@plugin('battery') +def battery_WIN32(jarvis, s): + """ + Provides basic info about battery fo win32 + """ + # https://stackoverflow.com/a/41988506/6771356 + import psutil + + def secs2hours(secs): + mm, ss = divmod(secs, 60) + hh, mm = divmod(mm, 60) + return "%d:%02d:%02d" % (hh, mm, ss) + + batt = psutil.sensors_battery() + if batt.power_plugged: + jarvis.say("Battery is charging: %s%%" % batt.percent) + else: + jarvis.say("charge = %s%%, time left = %s" % (batt.percent, secs2hours(batt.secsleft))) + + @require(platform=LINUX, native='upower') @plugin('battery') -def battery(jarvis, s): +def battery_LINUX(jarvis, s): """ Provides battery status like battery percentage and if the battery is charging or not diff --git a/jarviscli/plugins/clock.py b/jarviscli/plugins/clock.py index 5f6e51882..bc4d2c0f3 100644 --- a/jarviscli/plugins/clock.py +++ b/jarviscli/plugins/clock.py @@ -10,7 +10,6 @@ def clock(jarvis, s): jarvis.say(ctime(), Fore.BLUE) -@require(native='termdown') @plugin('stopwatch') def stopwatch(jarvis, s): """ @@ -21,10 +20,9 @@ def stopwatch(jarvis, s): SPACE Pause Q Quit """ - system("termdown") + system("python -m termdown") -@require(native="termdown") @plugin('timer') def timer(jarvis, s): """ @@ -43,5 +41,5 @@ def timer(jarvis, s): if k[0] == '': jarvis.say("Please specify duration") return - timer_cmd = "termdown " + k[0] + timer_cmd = "python -m termdown " + k[0] system(timer_cmd) diff --git a/jarviscli/plugins/ip.py b/jarviscli/plugins/ip.py index 23d770c56..2fc3078f1 100644 --- a/jarviscli/plugins/ip.py +++ b/jarviscli/plugins/ip.py @@ -2,7 +2,7 @@ from colorama import Fore from utilities.GeneralUtilities import executable_exists -from plugin import plugin, require, UNIX +from plugin import plugin, require, UNIX, WINDOWS @require(platform=UNIX) @@ -36,3 +36,16 @@ def _get_public_ip(self, jarvis): system(self._public_ip_v4) jarvis.say("Public ip v6 address :", Fore.BLUE) system(self._public_ip_v6) + + +@require(platform=WINDOWS) +@plugin('ip') +def ip_WIN32(jarvis, s): + """ + Returns information about IP for windows + """ + import socket + + hostname = socket.gethostname() + IP = socket.gethostbyname(hostname) + jarvis.say("IP address: " + str(IP)) diff --git a/jarviscli/plugins/shutdown.py b/jarviscli/plugins/shutdown.py index a213979fb..755779657 100644 --- a/jarviscli/plugins/shutdown.py +++ b/jarviscli/plugins/shutdown.py @@ -4,7 +4,7 @@ @require(platform=LINUX) @plugin('shutdown') -def shutdown(jarvis, s): +def shutdown_LINUX(jarvis, s): """ Shutdown the system Uses: @@ -23,7 +23,7 @@ def shutdown(jarvis, s): @require(platform=MACOS) @plugin('shutdown') -def shutdown(jarvis, s): +def shutdown_MACOS(jarvis, s): """ Shutdown the system Uses: @@ -42,7 +42,7 @@ def shutdown(jarvis, s): @require(platform=WINDOWS) @plugin('shutdown') -def shutdown(jarvis, s): +def shutdown_WIN32(jarvis, s): """ Shutdown the system Uses: @@ -61,7 +61,7 @@ def shutdown(jarvis, s): @require(platform=LINUX) @plugin('reboot') -def reboot(jarvis, s): +def reboot_LINUX(jarvis, s): """Reboot the system""" if s == '': s = jarvis.input('In how many minutes?: ') @@ -71,7 +71,7 @@ def reboot(jarvis, s): @require(platform=MACOS) @plugin('reboot') -def reboot(jarvis, s): +def reboot_MACOS(jarvis, s): """Reboot the system""" string = 'sudo shutdown -r now' os.system(string) @@ -79,7 +79,7 @@ def reboot(jarvis, s): @require(platform=WINDOWS) @plugin('reboot') -def reboot(jarvis, s): +def reboot_WIN32(jarvis, s): """Reboot the system""" if s == '': s = jarvis.input('In how many seconds?: ') @@ -87,61 +87,61 @@ def reboot(jarvis, s): os.system(string) +@require(native="systemctl", platform=LINUX) +@plugin('hibernate') +def hibernate_LINUX(jarvis, s): + """ + Hibernate - also known as "Suspend to Disk" + + Saves everything running to disk and performs shutdown. + Next reboot computer will restore everything - including + Programs and open files like the shutdown never happened. + """ + os.system('sudo systemctl hibernate') + + @require(platform=WINDOWS) @plugin('hibernate') -def reboot(jarvis, s): +def hibernate_WIN32(jarvis, s): """Hibernates the system""" string = 'shutdown /h' os.system(string) -@require(platform=WINDOWS) -@plugin('log off') -def reboot(jarvis, s): - """Log off the system""" - string = 'shutdown /l' - os.system(string) +@require(native="systemctl", platform=LINUX) +@plugin('hybridsleep') +def hybridsleep_LINUX(jarvis, s): + """ + Hybrid sleep. + Will quickly wake up but also survive power cut. + Performs both suspend AND hibernate. + Will quickly wake up but also survive power cut. + """ + os.system("sudo systemctl hybrid-sleep") @require(platform=WINDOWS) @plugin('hybridsleep') -def reboot(jarvis, s): +def hybridsleep_WIN32(jarvis, s): """Performs shutdown and prepares forfast startup""" string = 'shutdown /hybrid' os.system(string) +@require(platform=WINDOWS) +@plugin('log off') +def log_off_WIN32(jarvis, s): + """Log off the system""" + string = 'shutdown /l' + os.system(string) + + @require(native="systemctl", platform=LINUX) @plugin('suspend') -def suspend(jarvis, s): +def suspend_LINUX(jarvis, s): """ Suspend (to RAM) - also known as Stand By or Sleep mode. Operate PC on a minimum to save power but quickly wake up. """ os.system('sudo systemctl suspend') - - -@require(native="systemctl", platform=LINUX) -@plugin('hibernate') -def hibernate(jarvis, s): - """ - Hibernate - also known as "Suspend to Disk" - - Saves everything running to disk and performs shutdown. - Next reboot computer will restore everything - including - Programs and open files like the shutdown never happened. - """ - os.system('sudo systemctl hibernate') - - -@require(native="systemctl", platform=LINUX) -@plugin('hybridsleep') -def hybridsleep(jarvis, s): - """ - Hybrid sleep. - Will quickly wake up but also survive power cut. - Performs both suspend AND hibernate. - Will quickly wake up but also survive power cut. - """ - os.system("sudo systemctl hybrid-sleep") diff --git a/jarviscli/plugins/systemOptions.py b/jarviscli/plugins/systemOptions.py index 70481f177..10cc84968 100644 --- a/jarviscli/plugins/systemOptions.py +++ b/jarviscli/plugins/systemOptions.py @@ -2,7 +2,7 @@ from platform import architecture, dist, release, mac_ver from platform import system as sys from colorama import Fore, Style - +import psutil from plugin import LINUX, MACOS, WINDOWS, PYTHON2, PYTHON3, plugin, require @@ -78,7 +78,6 @@ def systeminfo_win(jarvis, s): os.system("systeminfo") -@require(native="free") @plugin("check ram") def check_ram(jarvis, s): """ @@ -86,4 +85,18 @@ def check_ram(jarvis, s): -- Examples: check ram """ - os.system("free -lm") + mem = psutil.virtual_memory() + + def format(size): + mb, _ = divmod(size, 1024 * 1024) + gb, mb = divmod(mb, 1024) + return "%s GB %s MB" % (gb, mb) + jarvis.say("Total RAM: %s" % (format(mem.total)), Fore.BLUE) + if mem.percent > 80: + color = Fore.RED + elif mem.percent > 60: + color = Fore.YELLOW + else: + color = Fore.GREEN + jarvis.say("Available RAM: %s" % (format(mem.available)), color) + jarvis.say("RAM used: %s%%" % (mem.percent), color) diff --git a/requirements.txt b/requirements.txt index a3f82c0d4..c37a10a86 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,7 @@ mock nltk pick pluginmanager +psutil pycricbuzz pydoc-markdown pync==1.6.1; sys_platform == 'darwin'