332 lines
No EOL
11 KiB
Python
332 lines
No EOL
11 KiB
Python
import sqlite3
|
|
from flask import g
|
|
from flask import Flask
|
|
app = Flask(__name__)
|
|
from functools import wraps
|
|
from flask import request, Response
|
|
from flask import render_template, redirect
|
|
from funkapi import FunkAPI
|
|
import json
|
|
import time
|
|
import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
import os
|
|
|
|
|
|
DATABASE = os.getenv("FUNK_DATABASE", 'database.db')
|
|
USERNAME = os.getenv("FUNK_USER", 'admin')
|
|
PASSWORD = os.getenv("FUNK_PASS", 'geheim')
|
|
ENABLED_AUTH = os.getenv("FUNK_AUTH", False)
|
|
|
|
#Helper
|
|
def get_db():
|
|
db = getattr(g, '_database', None)
|
|
if db is None:
|
|
db = g._database = sqlite3.connect(DATABASE)
|
|
return db
|
|
|
|
def check_auth(username, password):
|
|
"""This function is called to check if a username /
|
|
password combination is valid.
|
|
"""
|
|
return username == USERNAME and password == PASSWORD
|
|
|
|
def authenticate():
|
|
"""Sends a 401 response that enables basic auth"""
|
|
return Response(
|
|
'Could not verify your access level for that URL.\n'
|
|
'You have to login with proper credentials', 401,
|
|
{'WWW-Authenticate': 'Basic realm="Login Required"'})
|
|
|
|
def requires_auth(f):
|
|
@wraps(f)
|
|
def decorated(*args, **kwargs):
|
|
if not ENABLED_AUTH:
|
|
return f(*args, **kwargs)
|
|
auth = request.authorization
|
|
if not auth or not check_auth(auth.username, auth.password):
|
|
return authenticate()
|
|
return f(*args, **kwargs)
|
|
return decorated
|
|
|
|
# Functions
|
|
def function_updateAccount(number):
|
|
cur = get_db().cursor()
|
|
cur.execute("SELECT mail, password FROM accounts WHERE `number` = '%s'" % (number))
|
|
res = cur.fetchone()
|
|
api = FunkAPI(res[0], res[1])
|
|
|
|
plan = api.getCurrentPlan()["productServiceInfo"]["marketingInfo"]["name"]
|
|
usage = api.getData()["data"]["me"]["customerProducts"][0]["mobileNumbers"][0]["usage"]["usedDataPercentage"]
|
|
|
|
cur.execute("INSERT INTO updates VALUES (%s, %s, '%s', '%s')" % (
|
|
number,
|
|
int(time.time()),
|
|
plan,
|
|
usage
|
|
))
|
|
|
|
get_db().commit()
|
|
|
|
def function_speacialDays(number):
|
|
cur = get_db().cursor()
|
|
cur.execute("SELECT day, month, year, plan FROM special WHERE number = %s ORDER BY year, month, day" % number)
|
|
res = cur.fetchall()
|
|
days = []
|
|
for r in res:
|
|
day = {}
|
|
day["day"] = str(r[0])+"."+str(r[1])+"."+str(r[2])
|
|
day["plan"] = r[3]
|
|
days.append(day)
|
|
return days
|
|
|
|
|
|
|
|
def function_getAccounts(includePassword = False):
|
|
cur = get_db().cursor()
|
|
cur.execute("SELECT number, mail, password, owner, defaultPlan FROM accounts")
|
|
res = cur.fetchall()
|
|
accounts = []
|
|
for accountData in res:
|
|
lastUpdate = cur.execute("SELECT updateTime, plan, dataUsed FROM updates WHERE number = '%s' ORDER BY updateTime DESC LIMIT 1" % (accountData[0])).fetchone()
|
|
account = {}
|
|
account["number"] = accountData[0]
|
|
account["mail"] = accountData[1]
|
|
if includePassword:
|
|
account["password"] = accountData[2]
|
|
account["owner"] = accountData[3]
|
|
account["defaultPlan"] = accountData[4]
|
|
account["currentPlan"] = lastUpdate[1]
|
|
account["dataUsed"] = lastUpdate[2]
|
|
account["lastUpdate"] = lastUpdate[0]
|
|
accounts.append(account)
|
|
|
|
return accounts
|
|
|
|
def function_getAccount(number, includePassword = False):
|
|
cur = get_db().cursor()
|
|
cur.execute("SELECT number, mail, password, owner, defaultPlan FROM accounts WHERE number = %s" % (number))
|
|
accountData = cur.fetchone()
|
|
lastUpdate = cur.execute("SELECT updateTime, plan, dataUsed FROM updates WHERE number = '%s' ORDER BY updateTime DESC LIMIT 1" % (accountData[0])).fetchone()
|
|
account = {}
|
|
account["number"] = accountData[0]
|
|
account["mail"] = accountData[1]
|
|
if includePassword:
|
|
account["password"] = accountData[2]
|
|
account["owner"] = accountData[3]
|
|
account["defaultPlan"] = accountData[4]
|
|
account["currentPlan"] = lastUpdate[1]
|
|
account["dataUsed"] = lastUpdate[2]
|
|
account["lastUpdate"] = lastUpdate[0]
|
|
return account
|
|
|
|
def function_getPlanForDay(number, year, month, day):
|
|
cur = get_db().cursor()
|
|
dayPlan = cur.execute("SELECT plan FROM special WHERE number = %s AND day = %s AND month = %s AND year = %s" % (number, day, month, year)).fetchone()
|
|
if dayPlan:
|
|
return dayPlan[0]
|
|
else:
|
|
defaultPlan = cur.execute("SELECT defaultPlan FROM accounts WHERE number = %s" % (number)).fetchone()
|
|
return defaultPlan[0]
|
|
|
|
@app.route("/updateAll")
|
|
@requires_auth
|
|
def function_updateAccountsAtFunk():
|
|
cur = get_db().cursor()
|
|
today = datetime.datetime.now()
|
|
done = cur.execute("SELECT count(*) FROM run_actions WHERE year = %s AND month = %s AND day = %s" % (today.year, today.month, today.day)).fetchone()
|
|
|
|
if done[0] == 0:
|
|
numbers = cur.execute("SELECT number FROM accounts").fetchall()
|
|
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
|
|
|
|
for number in numbers:
|
|
print("Update Account: "+str(number[0]))
|
|
#function_updateAccount(number[0])
|
|
account = function_getAccount(number[0], True)
|
|
print(account)
|
|
nextPlan = function_getPlanForDay(number[0], tomorrow.year, tomorrow.month, tomorrow.day)
|
|
if account["currentPlan"] == nextPlan:
|
|
print("Plan match, nothing to do")
|
|
else:
|
|
api = FunkAPI(account["mail"], account["password"])
|
|
if nextPlan == "1 GB":
|
|
api.order1GBPlan()
|
|
elif nextPlan == "unlimited":
|
|
api.orderUnlimitedPlan()
|
|
elif nextPlan == "Break":
|
|
api.startPause()
|
|
else:
|
|
print("SOMETHING GO WRONG")
|
|
|
|
cur.execute("INSERT INTO run_actions VALUES (%s, %s, %s) " % (today.year, today.month, today.day))
|
|
get_db().commit()
|
|
|
|
return "OK";
|
|
|
|
|
|
|
|
else:
|
|
return "Done for today"
|
|
|
|
|
|
|
|
|
|
#Routes
|
|
@app.route("/")
|
|
@requires_auth
|
|
def hello():
|
|
return render_template("base.html")
|
|
|
|
@app.route('/setup', methods=['GET'])
|
|
@requires_auth
|
|
def setupDB():
|
|
cur = get_db().cursor()
|
|
cur.execute('''CREATE TABLE accounts (number integer, mail text, password text, owner text, defaultPlan text)''')
|
|
cur.execute('''CREATE TABLE updates (number integer, updateTime integer, plan text, dataUsed integer)''')
|
|
cur.execute('''CREATE TABLE special (number integer, day integer, month integer, year integer, plan text)''')
|
|
cur.execute('''CREATE TABLE run_actions (year integer, month integer, day integer)''')
|
|
get_db().commit()
|
|
return "Accounts"
|
|
|
|
# GUI
|
|
@app.route("/accounts")
|
|
@requires_auth
|
|
def gui_liste():
|
|
return render_template("list.html", accounts=function_getAccounts(), currentTime=int(time.time()))
|
|
|
|
@app.route("/account/<number>")
|
|
@requires_auth
|
|
def gui_account(number):
|
|
account = function_getAccount(number)
|
|
special_days = function_speacialDays(number)
|
|
|
|
return render_template("account.html", account=account, special_days=special_days, currentTime=int(time.time()))
|
|
|
|
@app.route("/account/<number>/special", methods=['POST'])
|
|
@requires_auth
|
|
def special_days(number):
|
|
start = datetime.datetime(int(request.form["from_year"]), int(request.form["from_month"]), int(request.form["from_day"]), 0, 0, 0)
|
|
ende = datetime.datetime(int(request.form["to_year"]), int(request.form["to_month"]), int(request.form["to_day"]), 0, 0, 0)
|
|
delta = ende - start
|
|
|
|
cur = get_db().cursor()
|
|
for i in range(delta.days + 1):
|
|
date = start + datetime.timedelta(days=i)
|
|
if request.form["plan"] == "Default":
|
|
cur.execute("DELETE FROM special WHERE number = %s AND year = %s AND month = %s AND day = %s" % (number, date.year, date.month, date.day))
|
|
else:
|
|
cur.execute("DELETE FROM special WHERE number = %s AND year = %s AND month = %s AND day = %s" % (number, date.year, date.month, date.day))
|
|
cur.execute("INSERT INTO special VALUES (%s, %s, %s, %s, '%s')" % (number, date.day, date.month, date.year, request.form["plan"]))
|
|
|
|
get_db().commit();
|
|
|
|
return redirect("/account/"+str(number), code=302)
|
|
|
|
@app.route("/account/<number>/days")
|
|
@requires_auth
|
|
def list_days(number):
|
|
start = datetime.datetime.now()
|
|
ende = start + relativedelta(months=2)
|
|
|
|
delta = ende - start
|
|
dayList = []
|
|
|
|
for i in range(delta.days + 1):
|
|
day = {}
|
|
date = start + datetime.timedelta(days=i)
|
|
day["date"] = str(date.day)+"."+str(date.month)+"."+str(date.year)
|
|
day["plan"] = function_getPlanForDay(number, date.year, date.month, date.day)
|
|
dayList.append(day)
|
|
|
|
|
|
return render_template("list_days.html", dayList=dayList)
|
|
|
|
@app.route("/account/add", methods=['GET'])
|
|
@requires_auth
|
|
def add_account_gui():
|
|
return render_template("account_add.html")
|
|
|
|
@app.route("/account/add", methods=['POST'])
|
|
@requires_auth
|
|
def add_account_gui_save():
|
|
r = addAccount()
|
|
return redirect("/accounts", code=302)
|
|
|
|
|
|
# API
|
|
@app.route('/api/accounts', methods=['GET'])
|
|
@requires_auth
|
|
def listAccounts():
|
|
resData = function_getAccounts()
|
|
response = {"success": True, "data": resData}
|
|
return json.dumps(response)
|
|
|
|
@app.route('/api/account/<number>/update', methods=['GET'])
|
|
@requires_auth
|
|
def updateAccount(number):
|
|
function_updateAccount(number)
|
|
response = {"success": True}
|
|
return json.dumps(response)
|
|
|
|
@app.route('/api/account/<number>/changeDafault', methods=['POST'])
|
|
@requires_auth
|
|
def changeDefault(number):
|
|
cur = get_db().cursor()
|
|
default = request.form["plan"]
|
|
cur.execute("UPDATE accounts SET `defaultPlan` = '%s' WHERE `number` = %s" % (default, number))
|
|
get_db().commit();
|
|
response = {"success": True}
|
|
return json.dumps(response)
|
|
|
|
@app.route('/api/accounts', methods=['POST'])
|
|
@requires_auth
|
|
def addAccount():
|
|
cur = get_db().cursor()
|
|
mail = request.form["mail"]
|
|
password = request.form["password"]
|
|
response = {}
|
|
response["success"] = False
|
|
response["msg"] = ""
|
|
|
|
try:
|
|
api = FunkAPI(mail, password)
|
|
personalData = api.getPersonalInfo()
|
|
except Exception:
|
|
response["msg"] = "Autherized failed, wrong mail/password?"
|
|
return json.dumps(response)
|
|
|
|
plan = api.getCurrentPlan()["productServiceInfo"]["marketingInfo"]["name"]
|
|
name = personalData["firstName"]+" "+personalData["lastName"]
|
|
|
|
# getUsage
|
|
data = api.getData()
|
|
number = data["data"]["me"]["customerProducts"][0]["mobileNumbers"][0]["number"]
|
|
|
|
|
|
#number integer, mail text, password text, owner text, defaultPlan text
|
|
cur.execute("INSERT INTO accounts VALUES ('%s', '%s', '%s', '%s', '%s')" % (
|
|
number,
|
|
mail,
|
|
password,
|
|
name,
|
|
plan
|
|
))
|
|
|
|
get_db().commit()
|
|
function_updateAccount(number)
|
|
|
|
response["success"] = True
|
|
response["data"] = {"name": name}
|
|
|
|
return json.dumps(response)
|
|
#SQLITE
|
|
|
|
@app.teardown_appcontext
|
|
def close_connection(exception):
|
|
db = getattr(g, '_database', None)
|
|
if db is not None:
|
|
db.close()
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True,host='0.0.0.0') |