Skip to content

Commit

Permalink
ver 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tabVersion committed May 23, 2020
0 parents commit 9136775
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 0 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# WECHAT NOTIFY

Many scripts today may take a long time to run, such as deep learning tasks. We wonder to check the results immediately after its accomplishment but keeping an eye on the process is not desirable.

This project is aimed to notify you through WeChat when certain command is completed.

## requirements

This package rely on `requests`.

```bash
pip3 install requests
```

### SERVER CHAN

This project rely on [SERVER CHAN](http://sc.ftqq.com/3.version) to push notifications to WeChat. Please follow the instructions on the website and **set your SCKEY to environment variable** as `SERVER_CHAN_TOKEN`.

Your command's output and error will be write to file `stdout` and `stderr` regardless of whether notification will be push or not.

## usage

```bash
notify [bash command]
```

Note that special chars of bash, such as `>`, need to be escaped so that the script can capture the corrent bash command. For example:

```bash
notify python train.py \> trail.log
```

## example

WECHAT_NOTIFY will push three kinds of notifications.

* [Success]: inform you [what command, start time, how long the command takes, last three lines of output(if exists)]
<img src='imgs/success.png' height=300>
* [Failed]: inform you [what command, start time, how long the command takes, last three lines of stderr(if exists)]
<img src='imgs/failed.png' height=300>
<!-- ![img](imgs/failed.png) -->
* [Keyboard Interrupt]: inform you [what command, start time, 'Keyboard Interrupt']
<img src='imgs/kayboard.png' height=300>
<!-- ![img](imgs/kayboard.png) -->

## TODO

- [ ] unit test
- [ ] Email support
- [ ] test on WeChat Work
Binary file added imgs/failed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/kayboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/success.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from setuptools import setup

setup(name="wechat-notify",
description="notify you on Wechat when certain task is completed",
version="1.0",
author="Tab_version",
author_email="[email protected]",
packages=['wechat_notify'],
install_requires=[
'requests',
],
entry_points = {
'console_scripts': ['notify=wechat_notify.notify:main'],
},
include_package_data=True,
)
Empty file added wechat_notify/__init__.py
Empty file.
70 changes: 70 additions & 0 deletions wechat_notify/notify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import sys
import os
import subprocess
import requests
import time

def build_parser():
if len(sys.argv) == 1:
raise ValueError('please input command')
return sys.argv[1:]


def send_request(output, err, process, token, command, start, duration, is_win):
if output is not None:
output = output.decode('utf-8').split('\r\n') if is_win else output.decode('utf-8').split('\n')
with open('stdout', 'w') as f:
f.write('\n'.join(output))
if err is not None:
err = err.decode('utf-8').split('\r\n') if is_win else err.decode('utf-8').split('\n')
with open('stderr', 'w') as f:
f.write('\n'.join(err))
temp = None
# import ipdb; ipdb.set_trace()
if process.poll() == 0:
if output is not None:
output = [''] * 3 + output
temp = 'the following are last three lines of stdout:\n' + '\n'.join(output[-3:])
post_str = r'https://sc.ftqq.com/' + token + '.send?' + f'text=[Scuucess] command: ' + ' '.join(command) + f'&desp=start at {time.ctime(int(start))}\ttake time: {duration}\t' + (temp if temp is not None else '')
requests.post(post_str)
else:
if err is not None:
err = [''] * 3 + err
temp = 'the following are last three lines of stderr:\n' + '\n'.join(err[-3:])
# import ipdb; ipdb.set_trace()
post_str = r'https://sc.ftqq.com/' + token + '.send?' + f'text=[Failed] command: ' + ' '.join(command) + f'&desp=start at {time.ctime(int(start))}\ttake time: {duration}\terror code: {process.poll()}'+ (temp if temp is not None else '')
print(post_str)
requests.post(post_str)



def init():
try:
token = os.environ['SERVER_CHAN_TOKEN']
except KeyError:
print('environment variable `SERVER_CHAN_TOKEN` unfound')
exit(1)
return token

def main():
token = init()
start = time.time()
try:
command = build_parser()
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = process.communicate()

except KeyboardInterrupt:
print('keyboard')
process.kill()
requests.post(r'https://sc.ftqq.com/' + token + '.send?' + f'text=[Failed] command: ' + ' '.join(command) + f'&desp=start at {time.ctime(int(start))}\nbecause of Keyboard Interrupt')
exit(0)

duration = time.time() - start
is_win = (sys.platform == 'win32')
send_request(output=output, err=err, duration=duration, is_win=is_win,start=start, token=token, command=command, process=process)



if __name__ == "__main__":
main()

0 comments on commit 9136775

Please sign in to comment.