Last active
December 15, 2015 03:39
-
-
Save kyuucr/5195607 to your computer and use it in GitHub Desktop.
This is an Ubuntu Unity Indicator to track your Dorm internet usage in NTUST. Added manual update quota, changed html parser.
Written on Python 2.7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf8 -*- | |
import appindicator | |
import bs4 | |
import datetime | |
import glib | |
import gtk | |
import logging | |
import pynotify | |
import re | |
import requests | |
import socket | |
import sys | |
logging.basicConfig(level=logging.DEBUG) | |
capabilities = {'actions': False, | |
'body': False, | |
'body-hyperlinks': False, | |
'body-images': False, | |
'body-markup': False, | |
'icon-multi': False, | |
'icon-static': False, | |
'sound': False, | |
'image/svg+xml': False, | |
'private-synchronous': False, | |
'append': False, | |
'private-icon-only': False} | |
def initCaps(): | |
caps = pynotify.get_server_caps() | |
if caps is None: | |
print "Failed to receive server caps." | |
sys.exit(1) | |
for cap in caps: | |
capabilities[cap] = True | |
def printCaps(): | |
info = pynotify.get_server_info() | |
print "Name: " + info["name"] | |
print "Vendor: " + info["vendor"] | |
print "Version: " + info["version"] | |
print "Spec. Version: " + info["spec-version"] | |
caps = pynotify.get_server_caps() | |
if caps is None: | |
print "Failed to receive server caps." | |
sys.exit(1) | |
print "Supported capabilities/hints:" | |
if capabilities['actions']: | |
print "\tactions" | |
if capabilities['body']: | |
print "\tbody" | |
if capabilities['body-hyperlinks']: | |
print "\tbody-hyperlinks" | |
if capabilities['body-images']: | |
print "\tbody-images" | |
if capabilities['body-markup']: | |
print "\tbody-markup" | |
if capabilities['icon-multi']: | |
print "\ticon-multi" | |
if capabilities['icon-static']: | |
print "\ticon-static" | |
if capabilities['sound']: | |
print "\tsound" | |
if capabilities['image/svg+xml']: | |
print "\timage/svg+xml" | |
if capabilities['private-synchronous']: | |
print "\tprivate-synchronous" | |
if capabilities['append']: | |
print "\tappend" | |
if capabilities['private-icon-only']: | |
print "\tprivate-icon-only" | |
print "Notes:" | |
if info["name"] == "notify-osd": | |
print "\tx- and y-coordinates hints are ignored" | |
print "\texpire-timeout is ignored" | |
print "\tbody-markup is accepted but filtered" | |
else: | |
print "\tnone" | |
class ThreadClass(): | |
def __init__(self, menu_items): | |
self.__menu_items = menu_items | |
self.__set_menu_message_default() | |
self.__menu_items[4].set_label("Update now") | |
self.__menu_items[4].connect("activate", self.updateQuota) | |
self.__usage_alert = pynotify.Notification("NTUST Dormweb Indicator", "Your quota has reached 2.5 GB", "dialog-warning") | |
def run(self): | |
try: | |
self.updateQuota("") | |
except Exception: | |
# if anything happen, just set the default message | |
logging.exception("Something happened! Set default message..") | |
self.__set_menu_message_default() | |
ind.set_status(appindicator.STATUS_ATTENTION) | |
finally: | |
# set interval | |
logging.debug("UPDATED " + datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")) | |
glib.timeout_add(300000, self.run) | |
def updateQuota(self, w): | |
date = datetime.datetime.now() | |
# query IP address | |
logging.debug("Querying IP address..") | |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
s.connect(("netweb.ntust.edu.tw", 80)) | |
ip = s.getsockname()[0] | |
s.close() | |
logging.debug("IP " + ip) | |
# query usage | |
logging.debug("Querying Usage..") | |
usage = self.requestUsage(ip, date.strftime("%Y/%m/%d")) | |
logging.debug(usage) | |
if usage[0] > 2500000000: | |
self.__usage_alert.show() | |
ind.set_status(appindicator.STATUS_ATTENTION) | |
else: | |
ind.set_status(appindicator.STATUS_ACTIVE) | |
self.__set_menu_message([ | |
ip, | |
"{0:.2f}".format(usage[0] / 1000000) + " MB", | |
"{0:.2f}".format(usage[1] / 1000000) + " MB", | |
"{0:.2f}".format(usage[2] / 1000000) + " MB" | |
]) | |
def requestUsage(self, ip, datestring): | |
# define post variables then request to netweb page | |
payload = {"__EVENTTARGET": "ipdata", | |
"__EVENTARGUMENT": "", | |
"__VIEWSTATE": "dDwtNDY0NjA5NTM4O3Q8O2w8aTwyPjs+O2w8dDw7bDxpPDE+O2k8Mz47aTw1PjtpPDc+O2k8MTM+Oz47bDx0PDtsPGk8MT47aTw3PjtpPDk+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPOWci+eri+WPsOeBo+enkeaKgOWkp+WtuCDlsI3lpJbntrLot6/mtYHph4/mn6XoqaI7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPOeZu+WFpeaXpeacn++8mjIwMTMvMDMvMTk7Pj47Pjs7Pjt0PDtsPGk8MD47PjtsPHQ8O2w8aTwxPjtpPDI+Oz47bDx0PDtsPGk8MD47PjtsPHQ8dDw7O2w8aTwwPjs+Pjs7Pjs+Pjt0PDtsPGk8MT47PjtsPHQ8dDxwPHA8bDxEYXRhVGV4dEZpZWxkOz47bDxTdHJpbmdUZXh0Oz4+Oz47dDxpPDQ+O0A8Qnl0ZXM7S0I7TUI7R0I7PjtAPEJ5dGVzO0tCO01CO0dCOz4+Oz47Oz47Pj47Pj47Pj47Pj47dDw7bDxpPDc+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPFxlOz4+Oz47Oz47Pj47dDxwPHA8bDxUZXh0Oz47bDxcPGJyXD7ms6jmhI/vvJrlm6DntbHoqIjln7rmupbkuI3lkIzvvIzoq4vli7/oiIflgIvkurrpm7vohabmr5TovIPvvIzlpoLmnInllY/poYzoq4ttYWls5YiwIGNjcG9zdG1hbkBtYWlsLm50dXN0LmVkdS50dyDoqI7oq5bjgII7Pj47Pjs7Pjt0PHA8cDxsPFZpc2libGU7PjtsPG88Zj47Pj47PjtsPGk8MT47aTwzPjs+O2w8dDxwPHA8bDxUZXh0Oz47bDzoqbPntLDmtYHph4/mn6XoqaI7Pj47Pjs7Pjt0PEAwPHA8cDxsPFBhZ2VTaXplOz47bDxpPDMyNzYwPjs+Pjs+Ozs7Ozs7Ozs7Oz47Oz47Pj47dDxwPHA8bDxWaXNpYmxlOz47bDxvPGY+Oz4+Oz47bDxpPDE+O2k8NT47aTw3PjtpPDk+Oz47bDx0PHA8cDxsPFRleHQ7PjtsPCo7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPFxlOz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDwwOz4+Oz47Oz47dDxwPHA8bDxUZXh0Oz47bDxcZTs+Pjs+Ozs+Oz4+Oz4+Oz4+Oz52G6uOlzw4wrbT3T3UWSV19EjV9Q==", | |
"RB_1": "詳細流量查詢", | |
"un": "Bytes", | |
"do_date": datestring, | |
"ipdata": ip, | |
"hip": re.sub('[0-9]+\.[0-9]+$', '', ip), | |
"msg_sysadm": ",請撥分機6212洽管理者!", | |
"p_ip": ip, | |
"dorm": "", | |
"pdate": datestring, | |
"page_size": "32760", | |
"sel_str": "dodate='*****'", | |
"tablename": "ipflowtable", | |
"tot_columns": "4", | |
"tot_rows": "0", | |
"tinsert": "", | |
"hmaxlen": "10,14,14,14,13,10,13,6,6,13,20,15,15,15,15", | |
"od_str": "", | |
"un_v": "1"} | |
r = requests.post('http://netweb.ntust.edu.tw/dormweb/flowquery.aspx', data=payload) | |
# response text to DOM using BeautifulSoup | |
soup = bs4.BeautifulSoup(r.text, "html.parser") | |
total = float(soup.find(id="tablelist__ctl3_tid1")["value"].replace(",", "")) | |
upload = float(soup.find(id="tablelist__ctl3_tid2")["value"].replace(",", "")) | |
download = float(soup.find(id="tablelist__ctl3_tid3")["value"].replace(",", "")) | |
return [total, upload, download] | |
def __set_menu_message_default(self): | |
self.__set_menu_message(["N/A", "N/A", "N/A", "N/A"]) | |
def __set_menu_message(self, msg): | |
self.__menu_items[0].set_label("Local address: " + msg[0]) | |
self.__menu_items[1].set_label("Total: " + msg[1]) | |
self.__menu_items[2].set_label("Upload: " + msg[2]) | |
self.__menu_items[3].set_label("Download: " + msg[3]) | |
if __name__ == "__main__": | |
if not pynotify.init("summary-body"): | |
sys.exit(1) | |
# call this so we can savely use capabilities dictionary later | |
initCaps() | |
# show what's supported | |
printCaps() | |
ind = appindicator.Indicator("ntust-dormweb-indicator", | |
"nm-adhoc", | |
appindicator.CATEGORY_APPLICATION_STATUS) | |
ind.set_status(appindicator.STATUS_ACTIVE) | |
ind.set_attention_icon("new-messages-red") | |
# create a menu | |
menu = gtk.Menu() | |
# create some menu items | |
menu_items = [] | |
for x in xrange(1, 6): | |
menu_item = gtk.MenuItem() | |
menu_items.append(menu_item) | |
menu.append(menu_item) | |
menu_item.show() | |
# set the menu | |
ind.set_menu(menu) | |
# fire up the thread! | |
t = ThreadClass(menu_items) | |
t.run() | |
gtk.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment