Compare commits

...

10 Commits

40 changed files with 1659 additions and 187 deletions

2
.gitignore vendored
View File

@ -158,4 +158,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
config.ini config.ini

37
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,37 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-docstring-first
- id: debug-statements
- id: double-quote-string-fixer
- id: requirements-txt-fixer
- id: check-added-large-files
- id: check-ast
- id: check-builtin-literals
- id: check-case-conflict
- id: destroyed-symlinks
- id: check-merge-conflict
- id: debug-statements
- id: detect-private-key
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: file-contents-sorter
- repo: https://github.com/hhatto/autopep8
rev: v2.1.0
hooks:
- id: autopep8
- repo: https://github.com/asottile/add-trailing-comma
rev: v3.1.0
hooks:
- id: add-trailing-comma
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.2
hooks:
- id: pyupgrade
- repo: https://github.com/abdelrahman0w/ouro
rev: v0.2.0
hooks:
- id: ouro

View File

@ -1,7 +1,66 @@
# BillPay # <img src="https://git.cubable.date/BillPay/app/~raw/dev/assets/icon.png" alt="icon" width="45" height="45"/> BillPay (WIP)
To run the app: A fully Independent Application for cross platform
```
flet run [app_directory] [![wakatime](https://wakatime.com/badge/user/198abec6-27b2-419b-87cf-60c4107b01be/project/018ef6c9-2350-4cfa-a556-ccadc51e0aa9.svg)](https://wakatime.com/badge/user/198abec6-27b2-419b-87cf-60c4107b01be/project/018ef6c9-2350-4cfa-a556-ccadc51e0aa9)
```
## 🎯 Purpose for BillPay
It has been difficult for me to manage my bills by having multiple apps installed on my mobile device, and I am sure many other people do too. There are many services here that provide all in one bill pay but they are so locked out we have to login to pay, and to pay we have to communicate with a third party bank account to send it credit so we can process our payments. If those services go down there is no possibility that we can further process our bills through those platforms.
So what could be better than having a fully independent App where YOU control YOUR bills and payments without having to rely on a thirdparty service.
## 💧 Features
**🈚 Independent:**
Application doesnt rely on any thirdparty service to process any bill payments other than banks which are included by the vendor
**🧩 Plugins:**
Apps can be pluggable, if user dont want to see them they can turn it off
***♻️ Backup & Restore:***
Backup Payment History and Restore them on any device
## ⏬ Downloads
- Grab your own copy from [Builds](https://git.cubable.date/BillPay/app/~builds)
## 🦮 Build Guide
### 📜 Requirements
- flutter
- python 3.11.1
- android studio (for android)
- Visual Studio (for Windows)
- Xcode (for IOS)
- Chrome (for Web)
### 🛠️ Build Steps
- Create a python virtualenv: `python -m venv venv`
- Activate virtualenv:
- Windows: `.\venv\Scripts\activate`
- Linux/MacOS: `source venv/bin/activate`
- Install requirements: `pip install -r requirements.txt`
- Run interactive for debugging:
- `flet run --<platform>` where the platform is either `ios` `android` `web`
- To Build Release:
- `flet build <platform> --verbose` where `<platform>` is either `ios` `android` `web`
### Developed with ❤️:
<a href="https://penpot.app">
<img src="https://www.svgrepo.com/download/432263/penpot.svg" alt="penpot" width="50" height="50" class="penpot-color"/>
<style>
.penpot-color{
filter: invert(40%) sepia(0%) saturate(2476%);
}
</style>
</a>
<a href="https://python.org">
<img src="https://asset.brandfetch.io/idbpOFBgcc/idcTemqrrW.svg" alt="python" width="50" height="50"/>
</a>
<a href="https://flutter.dev">
<img src="https://asset.brandfetch.io/idEMZUpQF7/idvArxAqXg.svg" alt="drawing" width="50" height="50"/>
</a>
<a href="https://flet.dev">
<img src="https://github.com/flet-dev/flet/blob/main/media/logo/Icon-192.png?raw=true" alt="drawing" width="50" height="50"/>
</a>

5
apps/__init__.py Normal file
View File

@ -0,0 +1,5 @@
from .apps import Apps
__all__ = [
'Apps',
]

448
apps/apps.py Normal file
View File

@ -0,0 +1,448 @@
import flet as ft
from utils import AppView, Title
from modules.settings import config
from modules.home import AppRow
def Apps(page: ft.Page):
AppRow.controls = []
appsContainer = ft.ListView(
expand=True,
)
appList = ft.Container(
content=ft.Column(
controls=[],
),
)
appsContainer.controls.append(
appList,
)
if config.getint('apps', 'dhiraagu') == 1:
appList.content.controls.append(
ft.Card(
content=ft.Container(
ink=True,
content=ft.Column(
[
ft.ListTile(
leading=ft.Image(
border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN,
src='https://asset.brandfetch.io/idZJsIaold/id9-VJM_HU.png',
),
title=ft.Text('Dhiraagu'),
subtitle=ft.Text(
'An ISP Service.',
),
),
],
),
padding=10,
on_click=lambda _: page.go('/apps/dhiraagu'),
),
),
)
AppRow.controls.append(
ft.Text('Dhiraagu'),
)
AppRow.controls.append(
ft.Container(
margin=10,
padding=10,
bgcolor=ft.colors.with_opacity(0.1, '#000000'),
border_radius=10,
content=ft.Row(
[
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.ACCOUNT_BOX,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/dhiraagu',
),
),
ft.Container(
content=ft.Text(
'Gift',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.ELECTRIC_BOLT,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/dhiraagu',
),
),
ft.Container(
content=ft.Text(
'Reload',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.DASHBOARD,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/dhiraagu',
),
),
ft.Container(
content=ft.Text(
'Usage',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.RECEIPT,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/dhiraagu',
),
),
ft.Container(
content=ft.Text(
'Bills',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
],
alignment=ft.MainAxisAlignment.CENTER,
),
),
)
if config.getint('apps', 'ooredoo') == 1:
appList.content.controls.append(
ft.Card(
content=ft.Container(
ink=True,
content=ft.Column(
[
ft.ListTile(
leading=ft.Image(
border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN,
src='https://asset.brandfetch.io/idR1xFKHLD/idu6J-WQsm.jpeg',
),
title=ft.Text('Ooredoo'),
subtitle=ft.Text(
'An ISP Service.',
),
),
],
),
padding=10,
on_click=lambda _: page.go('/apps/ooredoo'),
),
),
)
AppRow.controls.append(
ft.Text('Ooredoo'),
)
AppRow.controls.append(
ft.Container(
margin=10,
padding=10,
bgcolor=ft.colors.with_opacity(0.1, '#000000'),
border_radius=10,
content=ft.Row(
[
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.SETTINGS_PHONE,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/ooredoo',
),
),
ft.Container(
content=ft.Text(
'Add-ons',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.ELECTRIC_BOLT,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/ooredoo',
),
),
ft.Container(
content=ft.Text(
'Raastas',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.DASHBOARD,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/ooredoo',
),
),
ft.Container(
content=ft.Text(
'Balance',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.RECEIPT,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/apps/ooredoo',
),
),
ft.Container(
content=ft.Text(
'Bills',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
],
alignment=ft.MainAxisAlignment.CENTER,
),
),
)
if config.getint('apps', 'mwsc') == 1:
appList.content.controls.append(
ft.Card(
content=ft.Container(
ink=True,
content=ft.Column(
[
ft.ListTile(
leading=ft.Image(
border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN,
src='https://asset.brandfetch.io/idOZWUOUm-/idNastd9Bg.jpeg',
),
title=ft.Text('MWSC'),
subtitle=ft.Text(
'Water Bills',
),
),
],
),
padding=10,
on_click=lambda _: page.go('/apps/mwsc'),
),
),
)
if config.getint('apps', 'stelco') == 1:
appList.content.controls.append(
ft.Card(
content=ft.Container(
ink=True,
content=ft.Column(
[
ft.ListTile(
leading=ft.Image(
border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN,
src='https://www.stelco.com.mv/wp-content/uploads/2022/02/unnamed.png',
),
title=ft.Text('STELCO'),
subtitle=ft.Text(
'Electricity Bills',
),
),
],
),
padding=10,
on_click=lambda _: page.go('/apps/stelco'),
),
),
)
if config.getint('apps', 'medianet') == 1:
appList.content.controls.append(
ft.Card(
content=ft.Container(
ink=True,
content=ft.Column(
[
ft.ListTile(
leading=ft.Image(
border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN,
src='https://asset.brandfetch.io/idLMZnv5SC/iduyX4keYN.jpeg',
),
title=ft.Text('Dhiraagu'),
subtitle=ft.Text(
'Online Television Service',
),
),
],
),
padding=10,
on_click=lambda _: page.go('/apps/medianet'),
),
),
)
if not AppRow.controls:
AppRow.controls.append(
ft.Container(
content=ft.Card(
content=ft.Container(
content=ft.Container(
ft.Text(
'Add a module from settings to see shortcuts here.',
text_align=ft.TextAlign.CENTER,
),
),
padding=10,
on_click=None,
),
),
),
)
if not appList.content.controls:
appList.content.controls.append(
ft.Text(
'Add a module from settings to see shortcuts here.',
text_align=ft.TextAlign.CENTER,
),
)
appList.alignment = ft.alignment.center
appList.expand = True
return AppView(
'/apps',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/'),
),
title=ft.Text(Title(str(__file__))),
bgcolor=ft.colors.TRANSPARENT,
),
appsContainer,
],
)

13
apps/plugins/__init__.py Normal file
View File

@ -0,0 +1,13 @@
from .dhiraagu import Dhiraagu
from .ooredoo import Ooredoo
from .medianet import Medianet
from .mwsc import Mwsc
from .stelco import Stelco
__all__ = [
'Dhiraagu',
'Ooredoo',
'Medianet',
'Stelco',
'Mwsc',
]

View File

@ -0,0 +1,5 @@
from .app import App as Dhiraagu
__all__ = [
'Dhiraagu',
]

View File

@ -0,0 +1,18 @@
import flet as ft
from utils import AppView
def App(page: ft.Page):
return AppView(
'/apps/dhiraagu',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/apps'),
),
title=ft.Text('Dhiraagu'),
bgcolor=ft.colors.TRANSPARENT,
),
],
)

View File

@ -0,0 +1,5 @@
from .app import App as Medianet
__all__ = [
'Medianet',
]

View File

@ -0,0 +1,18 @@
import flet as ft
from utils import AppView
def App(page: ft.Page):
return AppView(
'/apps/medianet',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/apps'),
),
title=ft.Text('Medianet'),
bgcolor=ft.colors.TRANSPARENT,
),
],
)

View File

@ -0,0 +1,5 @@
from .app import App as Mwsc
__all__ = [
'Mwsc',
]

18
apps/plugins/mwsc/app.py Normal file
View File

@ -0,0 +1,18 @@
import flet as ft
from utils import AppView
def App(page: ft.Page):
return AppView(
'/apps/mwsc',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/apps'),
),
title=ft.Text('MWSC'),
bgcolor=ft.colors.TRANSPARENT,
),
],
)

View File

@ -0,0 +1,5 @@
from .app import App as Ooredoo
__all__ = [
'Ooredoo',
]

View File

@ -0,0 +1,18 @@
import flet as ft
from utils import AppView
def App(page: ft.Page):
return AppView(
'/apps/ooredoo',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/apps'),
),
title=ft.Text('Ooredoo'),
bgcolor=ft.colors.TRANSPARENT,
),
],
)

View File

@ -0,0 +1,5 @@
from .app import App as Stelco
__all__ = [
'Stelco',
]

View File

@ -0,0 +1,18 @@
import flet as ft
from utils import AppView
def App(page: ft.Page):
return AppView(
'/apps/stelco',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/apps'),
),
title=ft.Text('STELCO'),
bgcolor=ft.colors.TRANSPARENT,
),
],
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

51
main.py
View File

@ -1,26 +1,61 @@
import flet as ft import flet as ft
from utils import views_handler from utils import views_handler
from modules.settings.functions import config
from utils import checkInternet
def main(page: ft.Page): def main(page: ft.Page):
page.title = "BillPay" page.title = 'BillPay'
# print("Initial route:", page.route) print('Initial route:', page.route)
def route_change(e): config.save('general', 'ignore_network', '0')
# print("Route change:", e.route)
def route_change(e: ft.ControlEvent):
print('Route change:', e.route)
page.views.clear() page.views.clear()
page.views.append( page.views.append(
views_handler(page)[page.route] views_handler(page)[page.route],
) )
page.update() page.update()
def view_pop(e): if not config.getint('general', 'ignore_network') and not checkInternet():
# print("View pop:", e.view) dlg = ft.CupertinoActionSheet(
title=ft.Text('No Internet'),
message=ft.Text(
'Please check your network connectivity and try again',
),
cancel=ft.CupertinoActionSheetAction(
content=ft.Text('Okay'),
on_click=lambda _: (
page.close_bottom_sheet() if checkInternet(
) else None, page.update(), None if e.route == '/' else page.go('/'),
),
),
actions=[
ft.CupertinoActionSheetAction(
content=ft.Text('Ignore Completely'),
is_destructive_action=True,
on_click=lambda e: (
page.close_bottom_sheet(), config.save(
'general', 'ignore_network', '1',
),
),
),
],
)
page.show_bottom_sheet(ft.CupertinoBottomSheet(dlg))
def view_pop(e: ft.ControlEvent):
print('View pop:', e.view)
page.views.pop() page.views.pop()
top_view = page.views[-1] top_view = page.views[-1]
page.go(top_view.route) page.go(top_view.route)
if config.get('general', 'theme') == 'dark':
page.theme_mode = ft.ThemeMode.DARK
else:
page.theme_mode = ft.ThemeMode.LIGHT
page.on_route_change = route_change page.on_route_change = route_change
page.on_view_pop = view_pop page.on_view_pop = view_pop
page.go(page.route) page.go(page.route)
ft.app(target=main, assets_dir="assets") ft.app(target=main, assets_dir='assets')

View File

@ -2,4 +2,4 @@ from .home import Home
from .settings import Settings from .settings import Settings
__all__ = ["Home", "Settings"] __all__ = ['Home', 'Settings', 'Apps']

View File

@ -1,33 +1,181 @@
import flet as ft import flet as ft
from utils import AppView, Title from utils import AppView, Title
from modules.settings import config from modules.settings import config
from datetime import datetime
def greet(time: datetime):
if 5 <= time.hour < 12:
return 'Goodmorning,'
elif 12 <= time.hour < 18:
return 'Goodafternoon,'
else:
return 'Goodevening,'
AppRow = ft.ResponsiveRow(
alignment=ft.MainAxisAlignment.CENTER,
)
def Home(page: ft.Page): def Home(page: ft.Page):
contentColumn = ft.Container(
padding=10,
content=ft.Column(
controls=[
ft.Text(
greet(datetime.now()),
size=50,
weight=ft.FontWeight.W_500,
),
ft.Text(
config.get('general', 'name').split(' ')[0],
size=40,
weight=ft.FontWeight.W_300,
),
ft.Divider(),
AppRow,
ft.Divider(),
ft.Container(
margin=10,
padding=10,
bgcolor=ft.colors.with_opacity(0.1, '#000000'),
border_radius=10,
content=ft.Row(
[
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.APPS,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go('/apps'),
),
ft.Container(
content=ft.Text(
'Apps',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.HISTORY,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda e: print(
'Clickable with Ink clicked!',
),
),
ft.Container(
content=ft.Text(
'History',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.LIST,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda e: print(
'Clickable with Ink clicked!',
),
),
ft.Container(
content=ft.Text(
'Misc.',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
ft.Column(
controls=[
ft.Container(
content=ft.Icon(
ft.icons.SETTINGS,
color=ft.colors.WHITE,
),
margin=10,
padding=10,
alignment=ft.alignment.center,
bgcolor=ft.colors.GREY_700,
width=60,
height=60,
border_radius=10,
ink=True,
on_click=lambda _: page.go(
'/settings',
),
),
ft.Container(
content=ft.Text(
'Settings',
text_align=ft.TextAlign.CENTER,
),
alignment=ft.alignment.center,
width=80,
),
],
),
],
alignment=ft.MainAxisAlignment.CENTER,
),
),
],
),
)
return AppView( return AppView(
"/", '/',
[ [
ft.AppBar( ft.AppBar(
title=ft.Text(Title(__file__)), title=ft.Text(Title(__file__)),
actions=[ # actions=[
ft.IconButton( # ft.IconButton(
icon=ft.icons.SETTINGS, # icon=ft.icons.SETTINGS,
on_click=lambda _: page.go("/settings"), # on_click=lambda _: page.go('/settings'),
) # ),
] # ],
),
ft.Container(
height=100,
padding=10,
content=ft.Column(
controls=[
ft.Text(
"Goodmorning,"
),
ft.Text(
config.get("general", "name")
)
],
),
), ),
contentColumn,
], ],
) )

View File

@ -1,4 +1,4 @@
from .settings import Settings from .settings import Settings
from .functions import config from .functions import config
__all__ = ["Settings", "config"] __all__ = ['Settings', 'config']

View File

@ -0,0 +1,13 @@
from .dhiraagu_settings import Settings as DhiraaguSettings
from .medianet_settings import Settings as MedianetSettings
from .mwsc_settings import Settings as MwscSettings
from .ooredoo_settings import Settings as OoredooSettings
from .stelco_settings import Settings as StelcoSettings
__all__ = [
'DhiraaguSettings',
'MedianetSettings',
'MwscSettings',
'OoredooSettings',
'StelcoSettings',
]

View File

@ -0,0 +1,117 @@
import flet as ft
from utils import AppView, Title
from ..functions import config
def Settings(page: ft.Page):
settingsContainer = ft.ListView(
expand=True,
)
settingsContainer.controls.append(ft.Text('General'))
def _on_enable_change(e: ft.ControlEvent):
if config.getint('apps', 'dhiraagu'):
config.save('apps', 'dhiraagu', '0')
else:
config.save('apps', 'dhiraagu', '1')
page.update()
generalSettings = ft.Container(
content=ft.Column(
controls=[
ft.Card(
content=ft.Container(
content=ft.Container(
ft.Switch(
label=' Enable this module',
on_change=_on_enable_change,
value=False,
),
),
padding=10,
on_click=None,
),
),
],
),
)
if config.getint('apps', 'dhiraagu') == 1:
generalSettings.content.controls[0].content.content.content.value = True
settingsContainer.controls.append(
generalSettings,
)
settingsContainer.controls.append(
ft.Divider(),
)
# main settings
settingsContainer.controls.append(ft.Text('Account'))
loginForm = ft.Column()
phoneInput = ft.Container(
content=ft.TextField(
config.get('dhiraagu', 'phone'),
label='Phone',
adaptive=True,
),
padding=10,
)
loginForm.controls.append(phoneInput)
otpInput = ft.Container(
content=ft.TextField(
config.get('dhiraagu', 'otp'),
label='OTP',
adaptive=True,
),
padding=10,
)
loginForm.controls.append(otpInput)
sendOTP = ft.CupertinoButton(
content=ft.Text('SEND OTP'),
opacity_on_click=0.3,
on_click=lambda e: print('clicked!'),
)
if config.get('dhiraagu', 'token'):
phoneInput.disabled = True
otpInput.disabled = True
sendOTP.disabled = True
log = ft.CupertinoButton(
content=ft.Text('LOG OUT'),
opacity_on_click=0.3,
on_click=lambda e: print('clicked!'),
)
else:
log = ft.CupertinoButton(
content=ft.Text('LOG IN'),
opacity_on_click=0.3,
on_click=lambda e: print('clicked!'),
)
buttons = ft.Row(
controls=[
sendOTP,
],
)
buttons.controls.append(
log,
)
loginForm.controls.append(
buttons,
)
settingsContainer.controls.append(
loginForm,
)
return AppView(
'/settings/dhiraagu',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/settings'),
),
title=ft.Text(Title(str(__file__))),
bgcolor=ft.colors.TRANSPARENT,
),
settingsContainer,
],
)

View File

@ -0,0 +1,56 @@
import flet as ft
from utils import AppView, Title
from ..functions import config
def Settings(page: ft.Page):
settingsContainer = ft.ListView(
expand=True,
)
settingsContainer.controls.append(ft.Text('General'))
def _on_enable_change(e: ft.ControlEvent):
if config.getint('apps', 'medianet'):
config.save('apps', 'medianet', '0')
else:
config.save('apps', 'medianet', '1')
page.update()
generalSettings = ft.Container(
content=ft.Column(
controls=[
ft.Card(
content=ft.Container(
content=ft.Container(
ft.Switch(
label=' Enable this module',
on_change=_on_enable_change,
value=False,
),
),
padding=10,
on_click=None,
),
),
],
),
)
if config.getint('apps', 'medianet') == 1:
generalSettings.content.controls[0].content.content.content.value = True
settingsContainer.controls.append(
generalSettings,
)
return AppView(
'/settings/medianet',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/settings'),
),
title=ft.Text(Title(str(__file__))),
bgcolor=ft.colors.TRANSPARENT,
),
settingsContainer,
],
)

View File

@ -0,0 +1,58 @@
import flet as ft
from utils import AppView, Title
from ..functions import config
ft.Control
def Settings(page: ft.Page):
settingsContainer = ft.ListView(
expand=True,
)
settingsContainer.controls.append(ft.Text('General'))
def _on_enable_change(e: ft.ControlEvent):
if config.getint('apps', 'mwsc'):
config.save('apps', 'mwsc', '0')
else:
config.save('apps', 'mwsc', '1')
page.update()
generalSettings = ft.Container(
content=ft.Column(
controls=[
ft.Card(
content=ft.Container(
content=ft.Container(
ft.Switch(
label=' Enable this module',
on_change=_on_enable_change,
value=False,
),
),
padding=10,
on_click=None,
),
),
],
),
)
if config.getint('apps', 'mwsc') == 1:
generalSettings.content.controls[0].content.content.content.value = True
settingsContainer.controls.append(
generalSettings,
)
return AppView(
'/settings/mwsc',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/settings'),
),
title=ft.Text(Title(str(__file__))),
bgcolor=ft.colors.TRANSPARENT,
),
settingsContainer,
],
)

View File

@ -0,0 +1,56 @@
import flet as ft
from utils import AppView, Title
from ..functions import config
def Settings(page: ft.Page):
settingsContainer = ft.ListView(
expand=True,
)
settingsContainer.controls.append(ft.Text('General'))
def _on_enable_change(e: ft.ControlEvent):
if config.getint('apps', 'ooredoo'):
config.save('apps', 'ooredoo', '0')
else:
config.save('apps', 'ooredoo', '1')
page.update()
generalSettings = ft.Container(
content=ft.Column(
controls=[
ft.Card(
content=ft.Container(
content=ft.Container(
ft.Switch(
label=' Enable this module',
on_change=_on_enable_change,
value=False,
),
),
padding=10,
on_click=None,
),
),
],
),
)
if config.getint('apps', 'ooredoo') == 1:
generalSettings.content.controls[0].content.content.content.value = True
settingsContainer.controls.append(
generalSettings,
)
return AppView(
'/settings/ooredoo',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/settings'),
),
title=ft.Text(Title(str(__file__))),
bgcolor=ft.colors.TRANSPARENT,
),
settingsContainer,
],
)

View File

@ -0,0 +1,56 @@
import flet as ft
from utils import AppView, Title
from ..functions import config
def Settings(page: ft.Page):
settingsContainer = ft.ListView(
expand=True,
)
settingsContainer.controls.append(ft.Text('General'))
def _on_enable_change(e: ft.ControlEvent):
if config.getint('apps', 'stelco'):
config.save('apps', 'stelco', '0')
else:
config.save('apps', 'stelco', '1')
page.update()
generalSettings = ft.Container(
content=ft.Column(
controls=[
ft.Card(
content=ft.Container(
content=ft.Container(
ft.Switch(
label=' Enable this module',
on_change=_on_enable_change,
value=False,
),
),
padding=10,
on_click=None,
),
),
],
),
)
if config.getint('apps', 'stelco') == 1:
generalSettings.content.controls[0].content.content.content.value = True
settingsContainer.controls.append(
generalSettings,
)
return AppView(
'/settings/stelco',
[
ft.AppBar(
leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go('/settings'),
),
title=ft.Text(Title(str(__file__))),
bgcolor=ft.colors.TRANSPARENT,
),
settingsContainer,
],
)

View File

@ -1,3 +1,4 @@
from .config import config from .config import config
from .theme import Theme from .theme import Theme
__all__ = ['config', 'Theme']
__all__ = ['config', 'Theme']

View File

@ -2,59 +2,69 @@ from configparser import ConfigParser
import os import os
static = """ static = """
[general] [general]
name = CustomIcon name =
phone = phone =
email = email =
nid =
theme = light
ignore_network = 0
[apps] [apps]
dhiraagu = true dhiraagu = 0
ooredoo = true ooredoo = 0
hdc = true mwsc = 0
mwsc = true stelco = 0
stelco = true medianet = 0
medianet = true
[dhiraagu] [dhiraagu]
phone = phone =
otp = otp =
cookie = token =
account =
[ooredoo] [ooredoo]
phone = phone =
otp = otp =
cookie = cookie =
[hdc] [hdc]
property = property =
nid = nid =
[mwsc] [mwsc]
meter_no = meter_no =
account_no = account_no =
mobile_no = mobile_no =
[stelco] [stelco]
account_no = account_no =
bill_no = bill_no =
[medianet] [medianet]
account_no = account_no =
nid = nid =
phone = phone =
""" """
class Config(ConfigParser): class Config(ConfigParser):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
if not os.path.exists("config.ini"): if not os.path.exists('config.ini'):
self.initialize(content=static) self.initialize(content=static)
self.read("config.ini") self.read('config.ini')
def initialize(self, content): def initialize(self, content):
with open("config.ini", 'a+') as file: with open('config.ini', 'a+') as file:
file.write(content) file.write(content)
def save(self, section, key, value):
config.set(section, key, value)
with open('config.ini', 'w') as configfile:
self.write(configfile)
self.read('config.ini')
config = Config()
config = Config()

View File

@ -1,16 +1,11 @@
import flet as ft import flet as ft
class Theme: class Theme:
def __init__(self, page: ft.Page) -> None: def __init__(self, page: ft.Page) -> None:
self.page = page self.page = page
def change(self, theme: ft.ThemeMode = None): def change(self, theme: ft.ThemeMode = None):
if theme: if theme:
self.page.theme_mode = theme self.page.theme_mode = theme
else: self.page.update()
self.page.theme_mode = (
ft.ThemeMode.DARK
if self.page.theme_mode == ft.ThemeMode.LIGHT
else ft.ThemeMode.LIGHT
)
self.page.update()

View File

@ -1,12 +1,158 @@
import flet as ft import flet as ft
from utils import AppView, Title from utils import AppView, Title
from .functions import Theme from .functions import Theme, config
def Settings(page: ft.Page): def Settings(page: ft.Page):
settingsContainer = ft.ListView( settingsContainer = ft.ListView(
expand=True expand=True,
) )
settingsContainer.controls.append(ft.Text("General")) settingsContainer.controls.append(ft.Text('General'))
def _on_name_change(e: ft.ControlEvent):
newName = ft.CupertinoTextField(value=config.get('general', 'name'))
dlg = ft.CupertinoAlertDialog(
modal=True,
title=ft.Text('Enter your Full name'),
content=newName,
actions=[
ft.CupertinoButton(
'Save',
on_click=lambda _: (
setattr(
dlg,
'open',
False,
),
config.save(
'general',
'name',
newName.value,
),
page.update(),
),
),
ft.CupertinoButton(
'Close',
on_click=lambda _: (
setattr(dlg, 'open', False),
page.update(),
),
),
],
)
page.dialog = dlg
dlg.open = True
page.update()
def _on_phone_change(e: ft.ControlEvent):
newPhone = ft.CupertinoTextField(value=config.get('general', 'phone'))
dlg = ft.CupertinoAlertDialog(
modal=True,
title=ft.Text('Enter your Mobile'),
content=newPhone,
actions=[
ft.CupertinoButton(
'Save',
on_click=lambda _: (
setattr(
dlg,
'open',
False,
),
config.save(
'general',
'phone',
newPhone.value,
),
page.update(),
),
),
ft.CupertinoButton(
'Close',
on_click=lambda _: (
setattr(dlg, 'open', False),
page.update(),
),
),
],
)
page.dialog = dlg
dlg.open = True
page.update()
def _on_email_change(e: ft.ControlEvent):
newEmail = ft.CupertinoTextField(value=config.get('general', 'email'))
dlg = ft.CupertinoAlertDialog(
modal=True,
title=ft.Text('Enter your Email'),
content=newEmail,
actions=[
ft.CupertinoButton(
'Save',
on_click=lambda _: (
setattr(
dlg,
'open',
False,
),
config.save(
'general',
'email',
newEmail.value,
),
page.update(),
),
),
ft.CupertinoButton(
'Close',
on_click=lambda _: (
setattr(dlg, 'open', False),
page.update(),
),
),
],
)
page.dialog = dlg
dlg.open = True
page.update()
def _on_nid_change(e: ft.ControlEvent):
newNID = ft.CupertinoTextField(value=config.get('general', 'nid'))
dlg = ft.CupertinoAlertDialog(
modal=True,
title=ft.Text('Enter your NID'),
content=newNID,
actions=[
ft.CupertinoButton(
'Save',
on_click=lambda _: (
setattr(
dlg,
'open',
False,
),
config.save(
'general',
'nid',
newNID.value,
),
page.update(),
),
),
ft.CupertinoButton(
'Close',
on_click=lambda _: (
setattr(dlg, 'open', False),
page.update(),
),
),
],
)
page.dialog = dlg
dlg.open = True
page.update()
generalSettings = ft.Container( generalSettings = ft.Container(
content=ft.Column( content=ft.Column(
controls=[ controls=[
@ -17,16 +163,16 @@ def Settings(page: ft.Page):
[ [
ft.ListTile( ft.ListTile(
leading=ft.Icon(ft.icons.PERSON), leading=ft.Icon(ft.icons.PERSON),
title=ft.Text("Username"), title=ft.Text('Username'),
subtitle=ft.Text( subtitle=ft.Text(
"The greeting message" 'The greeting message',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked username"), on_click=_on_name_change,
) ),
), ),
ft.Card( ft.Card(
content=ft.Container( content=ft.Container(
@ -35,16 +181,16 @@ def Settings(page: ft.Page):
[ [
ft.ListTile( ft.ListTile(
leading=ft.Icon(ft.icons.PHONE), leading=ft.Icon(ft.icons.PHONE),
title=ft.Text("Phone"), title=ft.Text('Phone'),
subtitle=ft.Text( subtitle=ft.Text(
"Personal Phone number" 'Personal Phone number',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked phone"), on_click=_on_phone_change,
) ),
), ),
ft.Card( ft.Card(
content=ft.Container( content=ft.Container(
@ -53,16 +199,16 @@ def Settings(page: ft.Page):
[ [
ft.ListTile( ft.ListTile(
leading=ft.Icon(ft.icons.EMAIL), leading=ft.Icon(ft.icons.EMAIL),
title=ft.Text("Email"), title=ft.Text('Email'),
subtitle=ft.Text( subtitle=ft.Text(
"Personal Email" 'Personal Email',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked email"), on_click=_on_email_change,
) ),
), ),
ft.Card( ft.Card(
content=ft.Container( content=ft.Container(
@ -71,54 +217,54 @@ def Settings(page: ft.Page):
[ [
ft.ListTile( ft.ListTile(
leading=ft.Icon(ft.icons.CARD_TRAVEL), leading=ft.Icon(ft.icons.CARD_TRAVEL),
title=ft.Text("NID"), title=ft.Text('NID'),
subtitle=ft.Text( subtitle=ft.Text(
"National Idenity Number" 'National Idenity Number',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked email"), on_click=_on_nid_change,
) ),
), ),
] ],
) ),
) )
settingsContainer.controls.append( settingsContainer.controls.append(
generalSettings generalSettings,
) )
# settingsContainer.controls.append(ft.Divider())
# settingsContainer.controls.append(ft.Text('Notifications'))
# notificationsSettings = ft.Container(
# content=ft.Column(
# controls=[
# ft.Card(
# content=ft.Container(
# ink=True,
# content=ft.Column(
# [
# ft.ListTile(
# leading=ft.Icon(ft.icons.TELEGRAM),
# title=ft.Text('Telegram'),
# subtitle=ft.Text(
# 'Telegram Notifications for reminders and Bill pays',
# ),
# ),
# ],
# ),
# padding=10,
# on_click=lambda _: print('clicked username'),
# ),
# ),
# ],
# ),
# )
# settingsContainer.controls.append(
# notificationsSettings,
# )
settingsContainer.controls.append(ft.Divider()) settingsContainer.controls.append(ft.Divider())
settingsContainer.controls.append(ft.Text("Notifications")) settingsContainer.controls.append(ft.Text('Apps'))
notificationsSettings = ft.Container(
content=ft.Column(
controls=[
ft.Card(
content=ft.Container(
ink=True,
content=ft.Column(
[
ft.ListTile(
leading=ft.Icon(ft.icons.TELEGRAM),
title=ft.Text("Telegram"),
subtitle=ft.Text(
"Telegram Notifications for reminders and Bill pays"
),
),
]
),
padding=10,
on_click=lambda _: print("clicked username"),
)
),
]
)
)
settingsContainer.controls.append(
notificationsSettings
)
settingsContainer.controls.append(ft.Divider())
settingsContainer.controls.append(ft.Text("Apps"))
appsSettings = ft.Container( appsSettings = ft.Container(
content=ft.Column( content=ft.Column(
controls=[ controls=[
@ -131,18 +277,18 @@ def Settings(page: ft.Page):
leading=ft.Image( leading=ft.Image(
border_radius=ft.border_radius.all(10), border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN, fit=ft.ImageFit.CONTAIN,
src="https://asset.brandfetch.io/idZJsIaold/id9-VJM_HU.png" src='https://asset.brandfetch.io/idZJsIaold/id9-VJM_HU.png',
), ),
title=ft.Text("Dhiraagu"), title=ft.Text('Dhiraagu'),
subtitle=ft.Text( subtitle=ft.Text(
"An ISP Service." 'An ISP Service.',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked dhiraagu"), on_click=lambda _: page.go('/settings/dhiraagu'),
) ),
), ),
ft.Card( ft.Card(
content=ft.Container( content=ft.Container(
@ -153,18 +299,18 @@ def Settings(page: ft.Page):
leading=ft.Image( leading=ft.Image(
border_radius=ft.border_radius.all(10), border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN, fit=ft.ImageFit.CONTAIN,
src="https://asset.brandfetch.io/idR1xFKHLD/idu6J-WQsm.jpeg" src='https://asset.brandfetch.io/idR1xFKHLD/idu6J-WQsm.jpeg',
), ),
title=ft.Text("Ooredoo"), title=ft.Text('Ooredoo'),
subtitle=ft.Text( subtitle=ft.Text(
"An ISP Service." 'An ISP Service.',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked ooredoo"), on_click=lambda _: page.go('/settings/ooredoo'),
) ),
), ),
ft.Card( ft.Card(
content=ft.Container( content=ft.Container(
@ -175,18 +321,18 @@ def Settings(page: ft.Page):
leading=ft.Image( leading=ft.Image(
border_radius=ft.border_radius.all(10), border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN, fit=ft.ImageFit.CONTAIN,
src="https://www.stelco.com.mv/wp-content/uploads/2022/02/unnamed.png" src='https://www.stelco.com.mv/wp-content/uploads/2022/02/unnamed.png',
), ),
title=ft.Text("STELCO"), title=ft.Text('STELCO'),
subtitle=ft.Text( subtitle=ft.Text(
"Electricity Bills" 'Electricity Bills',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked stelco"), on_click=lambda _: page.go('/settings/stelco'),
) ),
), ),
ft.Card( ft.Card(
content=ft.Container( content=ft.Container(
@ -197,18 +343,18 @@ def Settings(page: ft.Page):
leading=ft.Image( leading=ft.Image(
border_radius=ft.border_radius.all(10), border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN, fit=ft.ImageFit.CONTAIN,
src="https://asset.brandfetch.io/idOZWUOUm-/idNastd9Bg.jpeg" src='https://asset.brandfetch.io/idOZWUOUm-/idNastd9Bg.jpeg',
), ),
title=ft.Text("MWSC"), title=ft.Text('MWSC'),
subtitle=ft.Text( subtitle=ft.Text(
"Water Bills" 'Water Bills',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked mwsc"), on_click=lambda _: page.go('/settings/mwsc'),
) ),
), ),
ft.Card( ft.Card(
content=ft.Container( content=ft.Container(
@ -219,27 +365,41 @@ def Settings(page: ft.Page):
leading=ft.Image( leading=ft.Image(
border_radius=ft.border_radius.all(10), border_radius=ft.border_radius.all(10),
fit=ft.ImageFit.CONTAIN, fit=ft.ImageFit.CONTAIN,
src="https://asset.brandfetch.io/idLMZnv5SC/iduyX4keYN.jpeg" src='https://asset.brandfetch.io/idLMZnv5SC/iduyX4keYN.jpeg',
), ),
title=ft.Text("Medianet"), title=ft.Text('Medianet'),
subtitle=ft.Text( subtitle=ft.Text(
"Online Television Service" 'Online Television Service',
), ),
), ),
] ],
), ),
padding=10, padding=10,
on_click=lambda _: print("clicked medianet"), on_click=lambda _: page.go('/settings/medianet'),
) ),
), ),
] ],
) ),
) )
settingsContainer.controls.append(appsSettings) settingsContainer.controls.append(appsSettings)
settingsContainer.controls.append(ft.Divider()) settingsContainer.controls.append(ft.Divider())
settingsContainer.controls.append(ft.Text("Theme")) settingsContainer.controls.append(ft.Text('Theme'))
def _on_theme_change(e):
Theme(page).change() def _on_theme_change(e: ft.ControlEvent):
if page.theme_mode == ft.ThemeMode.LIGHT:
e.value = False
config.save('general', 'theme', 'dark')
else:
e.value = True
config.save('general', 'theme', 'light')
Theme(page).change(
(
ft.ThemeMode.DARK
if page.theme_mode == ft.ThemeMode.LIGHT
else ft.ThemeMode.LIGHT
),
)
themeSettings = ft.Container( themeSettings = ft.Container(
content=ft.Column( content=ft.Column(
controls=[ controls=[
@ -247,30 +407,30 @@ def Settings(page: ft.Page):
content=ft.Container( content=ft.Container(
content=ft.Container( content=ft.Container(
ft.Switch( ft.Switch(
label=' Switch to dark theme',
on_change=_on_theme_change,
value=True, value=True,
label=" Switch to dark theme",
on_change=_on_theme_change
), ),
), ),
padding=10, padding=10,
on_click=None, on_click=None,
) ),
), ),
] ],
) ),
) )
settingsContainer.controls.append(themeSettings) settingsContainer.controls.append(themeSettings)
return AppView( return AppView(
"/settings", '/settings',
[ [
ft.AppBar( ft.AppBar(
leading=ft.IconButton( leading=ft.IconButton(
ft.icons.ARROW_BACK_IOS_NEW_ROUNDED, ft.icons.ARROW_BACK_IOS_NEW_ROUNDED,
on_click=lambda _: page.go("/") on_click=lambda _: page.go('/'),
), ),
title=ft.Text(Title(str(__file__))), title=ft.Text(Title(str(__file__))),
bgcolor=ft.colors.TRANSPARENT bgcolor=ft.colors.TRANSPARENT,
), ),
settingsContainer settingsContainer,
], ],
) )

View File

@ -1 +1,2 @@
flet==0.22.* flet==0.22.*
requests

View File

@ -1,9 +1,11 @@
from .view import AppView from .view import AppView
from .title import Title from .title import Title
from .views import views_handler from .views import views_handler
from .network import checkInternet
__all__ = [ __all__ = [
"AppView", 'AppView',
"Title", 'Title',
"views_handler" 'views_handler',
] 'checkInternet',
]

11
utils/network.py Normal file
View File

@ -0,0 +1,11 @@
import requests
def checkInternet():
try:
requests.get(
'https://rest.ensembl.org/info/ping?content-type=application/json',
)
return True
except requests.ConnectionError:
return False

View File

@ -1,4 +1,5 @@
import os import os
def Title(title: str): def Title(title: str):
return str(os.path.basename(title)).replace('.py', '').title() return str(os.path.basename(title)).split('.')[0].title().replace('_', ' ')

View File

@ -1,7 +1,8 @@
import flet as ft import flet as ft
class AppView(ft.View): class AppView(ft.View):
def __init__(self, route, controls): def __init__(self, route, controls):
super().__init__() super().__init__()
self.controls = controls self.controls = controls
self.route = route self.route = route

View File

@ -1,7 +1,33 @@
from modules import Home, Settings from modules import Home, Settings
from apps import Apps
from apps.plugins import Ooredoo, Dhiraagu, Medianet, Mwsc, Stelco
from modules.settings.appSettings import (
DhiraaguSettings,
MedianetSettings,
StelcoSettings,
OoredooSettings,
MwscSettings,
)
def views_handler(page): def views_handler(page):
return { views = {}
'/': Home(page), # root
'/settings': Settings(page) views['/'] = Home(page)
}
# settings
views['/settings'] = Settings(page)
views['/settings/dhiraagu'] = DhiraaguSettings(page)
views['/settings/ooredoo'] = OoredooSettings(page)
views['/settings/mwsc'] = MwscSettings(page)
views['/settings/medianet'] = MedianetSettings(page)
views['/settings/stelco'] = StelcoSettings(page)
# apps
views['/apps'] = Apps(page)
views['/apps/dhiraagu'] = Dhiraagu(page)
views['/apps/ooredoo'] = Ooredoo(page)
views['/apps/medianet'] = Medianet(page)
views['/apps/mwsc'] = Mwsc(page)
views['/apps/stelco'] = Stelco(page)
return views

5
wrappers/__init__.py Normal file
View File

@ -0,0 +1,5 @@
from .dhiraagu import DhiraaguAPI
__all__ = [
'DhiraaguAPI',
]

43
wrappers/dhiraagu.py Normal file
View File

@ -0,0 +1,43 @@
import requests
class DhiraaguAPI:
def __init__(
self,
phone: str = None,
otp: str = None,
token: str = None,
account: str = None,
) -> None:
self.phone = phone
self.otp = otp
self.token = token
self.account = account
self.headers = {
'Host': 'app-production.dhiraagu.com.mv',
'Content-Type': 'application/json',
'Connection': 'keep-alive',
'Accept': '*/*',
'User-Agent': 'MyDhiraagu/5.0 (mv.com.dhiraagu.app; build:1; iOS 17.5.0) Alamofire/5.6.1',
'Accept-Language': 'en-US;q=1.0, dv-MV;q=0.9, ar-MV;q=0.8',
# 'Content-Length': '33',
# 'Accept-Encoding': 'br;q=1.0, gzip;q=0.9, deflate;q=0.8',
}
if self.token:
self.headers['Authorization'] = f'Bearer {self.token}'
def login(self):
data = requests.post(
'https://app-production.dhiraagu.com.mv/auth',
json={
'number': self.phone,
'otp': self.otp,
},
)
return data.json()
def bills(self):
return requests.get(
f'https://app-production.dhiraagu.com.mv/io/v1/info/subscribers/{self.account}/liberate/billinfo',
headers=self.headers,
).json()