Compare commits

...

4 Commits

4 changed files with 123 additions and 31 deletions

View File

@ -1,12 +1,9 @@
USERNAME= USERNAME=
PASSWORD= PASSWORD=
TOTP_SEED= TOTP_SEED=
## username, password and totp_seed is not unused for now, please use cookie instead
#Cookie
QL_0=
IBSID=
PROFILE_ID=
PROFILE_TYPE=
ACCOUNT_NUMBER= ACCOUNT_NUMBER=
APP_DEBUG=true APP_DEBUG=true

View File

@ -1,6 +0,0 @@
import pyotp
import sys
seed = sys.argv[1]
totp = pyotp.TOTP(seed)
print(totp.now())

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

View File

@ -1,57 +1,158 @@
from flask import Flask, jsonify, request
import os import os
import pyotp import pyotp
import time
from urllib.parse import urlencode from urllib.parse import urlencode
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import requests import requests
from dotenv import load_dotenv from dotenv import load_dotenv
import json
class MIBLogin: class MIBLogin:
def __init__(self): def __init__(self):
self.session = requests.Session()
self.base_url = "https://faisanet.mib.com.mv" self.base_url = "https://faisanet.mib.com.mv"
self.headers = { self.headers = {
"User-Agent": "Mozilla/5.0 (give-api) ismath-owes-me-real-api/give-real-api AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36", "User-Agent": "Mozilla/5.0 (give-api) ismath-owes-me-real-api/give-real-api AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36",
"Accept": "*/*" "Accept": "*/*"
} }
self.last_cookie = None
self.last_renewal_time = 0
self.create_new_session()
def create_new_session(self):
self.session = requests.Session()
def get_login_page(self): def get_login_page(self):
response = self.session.get(f"{self.base_url}/auth", headers=self.headers) response = self.session.get(f"{self.base_url}/auth", headers=self.headers)
soup = BeautifulSoup(response.text, 'html.parser') soup = BeautifulSoup(response.text, 'html.parser')
return soup.find('input', {'name': 'rTag'})['value'] rtag_input = soup.find('input', {'name': 'rTag'})
if not rtag_input:
raise ValueError("Failed to find rTag input field in login page.")
return rtag_input['value']
def get_auth_type(self, rtag, username, retain=1): def get_auth_type(self, rtag, username, retain=1):
data = {'rTag': rtag, 'pgf01': username, 'retain': retain} data = {'rTag': rtag, 'pgf01': username, 'retain': retain}
headers = {**self.headers, 'Content-Type': 'application/x-www-form-urlencoded'} headers = {**self.headers, 'Content-Type': 'application/x-www-form-urlencoded'}
response = self.session.post(f"{self.base_url}/aAuth/getAuthType", headers=headers, data=urlencode(data)) response = self.session.post(
f"{self.base_url}/aAuth/getAuthType",
headers=headers,
data=urlencode(data)
)
return response.json() return response.json()
def login(self, username, password, retain=1): def login(self, username, password, retain=1):
rtag = self.get_login_page() rtag = self.get_login_page()
self.get_auth_type(rtag, username, retain) self.get_auth_type(rtag, username, retain)
data = {'rTag': rtag, 'pgf01': username, 'pgf02': password, 'retain': retain} data = {'rTag': rtag, 'pgf01': username, 'pgf02': password, 'retain': retain}
headers = {**self.headers, 'Content-Type': 'application/x-www-form-urlencoded'} headers = {**self.headers, 'Content-Type': 'application/x-www-form-urlencoded'}
self.session.post(f"{self.base_url}/aAuth", headers=headers, data=urlencode(data)) self.session.post(
f"{self.base_url}/aAuth",
headers=headers,
data=urlencode(data)
)
def auth_2fa(self, totp_seed): def auth_2fa(self, totp_seed):
self.session.get(f"{self.base_url}/auth2FA", headers=self.headers) self.session.get(f"{self.base_url}/auth2FA", headers=self.headers)
totp = pyotp.TOTP(totp_seed) totp = pyotp.TOTP(totp_seed)
data = {'otpType': 3, 'otp': totp.now()} data = {'otpType': 3, 'otp': totp.now()}
headers = {**self.headers, 'Content-Type': 'application/x-www-form-urlencoded'} headers = {**self.headers, 'Content-Type': 'application/x-www-form-urlencoded'}
self.session.post(f"{self.base_url}/aAuth2FA/verifyOTP", headers=headers, data=urlencode(data)) self.session.post(
f"{self.base_url}/aAuth2FA/verifyOTP",
return {cookie.name: cookie.value for cookie in self.session.cookies if cookie.name in ['IBSID', 'ql_0']} headers=headers,
data=urlencode(data)
)
def main(): cookies = {
load_dotenv() cookie.name: cookie.value
mib = MIBLogin() for cookie in self.session.cookies
mib.login(os.getenv('USERNAME'), os.getenv('PASSWORD')) if cookie.name in ['IBSID', 'ql_0']
cookies = mib.auth_2fa(os.getenv('TOTP_SEED')) }
self.last_cookie = cookies
self.last_renewal_time = time.time()
return cookies
# Print the cookies in JSON format def get_profile_rtag(self):
print(json.dumps(cookies, indent=4)) url = f"{self.base_url}/profiles"
response = self.session.get(url, headers=self.headers)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
profile_card = soup.find('div', {'class': 'card profile-card smooth smooth-shadow'})
if profile_card:
return profile_card.get('data-rt')
else:
raise ValueError("Failed to fetch profile rTag.")
else:
raise ValueError(f"Failed to retrieve profiles page. Status code: {response.status_code}")
if __name__ == "__main__": def switch_profile(self, profile_id, profile_type):
main() rtag = self.get_profile_rtag()
url = f"{self.base_url}/aProfileHandler/switchProfile"
data = {'rTag': rtag, 'profileId': profile_id, 'profileType': profile_type}
headers = {**self.headers, 'Content-Type': 'application/x-www-form-urlencoded'}
response = self.session.post(url, headers=headers, data=urlencode(data))
if response.status_code == 200:
result = response.json()
if result.get("success"):
print("Profile switched successfully.")
else:
raise ValueError("Failed to switch profile: " + result.get("reasonText", "Unknown error"))
else:
raise ValueError(f"Profile switch failed with status code: {response.status_code}")
def clear_cookie(self):
self.last_cookie = None
self.create_new_session()
# Initialize Flask app
app = Flask(__name__)
mib = MIBLogin()
load_dotenv()
def renew_cookie_internal():
try:
print(f"Starting cookie renewal process...")
mib.clear_cookie()
mib.login(os.getenv('USERNAME'), os.getenv('PASSWORD'))
cookies = mib.auth_2fa(os.getenv('TOTP_SEED'))
# Profile selection after successful login and 2FA
mib.switch_profile(os.getenv('PROFILE_ID'), os.getenv('PROFILE_TYPE'))
print(f"Cookie renewal and profile switch completed successfully")
return cookies
except Exception as e:
print(f"Error during cookie renewal: {str(e)}")
return {"error": str(e)}
@app.route('/getcookie', methods=['GET'])
def get_cookie():
client_ip = request.remote_addr
print(f"Providing cookie to: {client_ip}")
if mib.last_cookie:
return jsonify(mib.last_cookie)
else:
cookies = renew_cookie_internal()
if "error" in cookies:
return jsonify(cookies), 500
return jsonify(cookies)
@app.route('/newcookie', methods=['GET'])
def new_cookie():
client_ip = request.remote_addr
current_time = time.time()
# Check if less than 60 seconds since last renewal
if current_time - mib.last_renewal_time < 60:
print(f"Providing existing cookie to {client_ip} (last renewal was {int(current_time - mib.last_renewal_time)} seconds ago)")
return jsonify(mib.last_cookie)
print(f"Renewing cookie as requested by: {client_ip}")
cookies = renew_cookie_internal()
if "error" in cookies:
return jsonify(cookies), 500
return jsonify(cookies)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)