From 117ac3a45adf540d8f844127df69f46ded52ed02 Mon Sep 17 00:00:00 2001 From: Meghdad Date: Sun, 1 Jun 2025 23:25:32 +0330 Subject: [PATCH] implement using bargheman api --- .github/workflows/run-script.yml | 5 + main.py | 157 +++++++++++++++++-------------- requirements.txt | 1 + site-version.py | 95 +++++++++++++++++++ 4 files changed, 185 insertions(+), 73 deletions(-) create mode 100644 site-version.py diff --git a/.github/workflows/run-script.yml b/.github/workflows/run-script.yml index 251e7ff..2d00661 100644 --- a/.github/workflows/run-script.yml +++ b/.github/workflows/run-script.yml @@ -4,6 +4,9 @@ on: push: branches: - main + schedule: + - cron: "30 */3 * * *" + workflow_dispatch: jobs: run-script: @@ -25,7 +28,9 @@ jobs: - name: Run Python Script env: + BARGHEMAN_TOKEN: ${{ secrets.BARGHEMAN_TOKEN }} EITAAYAR_TOKEN: ${{ secrets.EITAAYAR_TOKEN }} + BILL_IDS: ${{ secrets.BILL_IDS }} CHAT_ID: ${{ secrets.CHAT_ID }} run: | python main.py diff --git a/main.py b/main.py index b17d5c0..7a21ded 100644 --- a/main.py +++ b/main.py @@ -1,95 +1,106 @@ import os -import re -import time +import json import requests -from bs4 import BeautifulSoup +from jdatetime import datetime, timedelta -token = os.getenv("EITAAYAR_TOKEN") -chat_id = os.getenv("CHAT_ID") +BARGHEMAN_TOKEN = os.getenv("BARGHEMAN_TOKEN") +EITAAYAR_TOKEN = os.getenv("EITAAYAR_TOKEN") +CHAT_ID = os.getenv("CHAT_ID") +BILL_IDS = os.getenv("BILL_IDS", "").split(",") +BLACKOUTS_FILE = "blackouts.json" -if not token: - raise EnvironmentError("EITAAYAR_TOKEN is not set!") +if not BARGHEMAN_TOKEN or not EITAAYAR_TOKEN or not CHAT_ID or len(BILL_IDS) == 0: + raise EnvironmentError("Environment is not ready!") -if not chat_id: - raise EnvironmentError("CHAT_ID is not set!") +today = datetime.now() +to_date = today + timedelta(days=5) -def send_message(text: str) -> dict: - sent_at: int = int(time.time()) - url = f'https://eitaayar.ir/api/{token}/sendMessage?chat_id={chat_id}&text={text}&title={sent_at=}' - return requests.get(url).json() +def get_blackouts(bill_id) -> list: + url = "https://uiapi2.saapa.ir/api/ebills/PlannedBlackoutsReport" + headers = { + "Authorization": f"Bearer {BARGHEMAN_TOKEN}", + } + payload = { + "bill_id": bill_id, + "from_date": today.strftime("%Y/%m/%d"), + "to_date": to_date.strftime("%Y/%m/%d"), + } + response = requests.post(url, headers=headers, json=payload) + return response.json().get("data", []) -def get_blockout_page() -> str: - blockout_link = 'https://qepd.co.ir/fa-IR/DouranPortal/6423' - blockout_link = 'https://re.rodad.net/blockout' - return requests.get(blockout_link).text +def load_blackouts() -> dict: + if os.path.exists(BLACKOUTS_FILE): + with open(BLACKOUTS_FILE, "r", encoding="utf-8") as f: + return json.load(f) + return {} -def convert_to_english_numbers(text): - persian_to_english = str.maketrans("۰۱۲۳۴۵۶۷۸۹", "0123456789") - return text.translate(persian_to_english) +def save_blackouts(data) -> None: + with open(BLACKOUTS_FILE, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) -def find_times(text: str) -> list[str]: - text = convert_to_english_numbers(text) - pattern = r"(\d{1,2}:\d{2}|\d{1,2})" - return re.findall(pattern, text) +def format_message(bill_id, entry): + RTLM = "\u200f" + return f"{RTLM}\n{RTLM}".join([ + f"⚡️ اطلاعیه خاموشی برق", + f"🆔 شناسه قبض: {bill_id}", + f"📅 تاریخ: {entry['outage_date']}", + f"⏰ ساعت: {entry['outage_start_time']} تا {entry['outage_stop_time']}", + f"📍 محل: {entry['outage_address']}", + f"📝 دلیل: {entry['reason_outage']}", + f"📥 ارسال شده در {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", + f".", + ]) -def is_time_past(time_str: str) -> bool: - try: - current_time = datetime.now(iran_tz).time() - - if ":" in time_str: - time_obj = datetime.strptime(time_str.strip(), "%H:%M").time() - else: - time_obj = datetime.strptime(time_str.strip(), "%H").time() - - return time_obj < current_time - except Exception: - return false -def make_message(html: str) -> str|None: - return None - if len(html) == 0: - return "خطا در خواندن صفحه!" - - soup = BeautifulSoup(html, 'html.parser') - # table = soup.find('table', id='ctl01_ctl00_myDataList') - - block_needle = 'بلوک A4' - try: - paragraphs = soup.find_all('p') - block = soup.find('p', string=lambda text: isinstance(text, str) and block_needle in text) - time_index = paragraphs.index(block) - 1 - text = paragraphs[time_index].get_text(separator='\n', strip=True) - start, end, *_ = find_times(text) - - if is_time_past(start): - return None - - return text - except: - return f"اطلاعات {block_needle} یافت نشد!" +def send_message(text): + url = f"https://eitaayar.ir/api/{EITAAYAR_TOKEN}/sendMessage" + payload = { + "chat_id": CHAT_ID, + "text": text, + "parse_mode": "HTML" + } + response = requests.get(url, params=payload) + if not response.ok: + print(f"❌ Failed to send message: {response.text}") def main() -> None: - try: - page = get_blockout_page() - message = make_message(page) - except requests.exceptions.Timeout: - message = 'درخواست ارسال نشد!' - - if not message: - return None - - response = send_message(message) - if not response.get('ok'): - if response.get('description'): - raise Exception(response.get('description')) - else: - raise Exception('something sent wrong!') + previous_data = load_blackouts() + updated_data = previous_data.copy() + + for bill_id in BILL_IDS: + new_blackouts = get_blackouts(bill_id) + old_blackouts = previous_data.get(bill_id, []) + + new_entries = [entry for entry in new_blackouts if entry not in old_blackouts] + + for entry in new_entries: + message = format_message(bill_id, entry) + send_message(message) + + if new_entries: + updated_data[bill_id] = old_blackouts + new_entries + + if updated_data != previous_data: + save_blackouts(updated_data) + os.system("git config --global user.name 'github-actions'") + os.system("git config --global user.email 'github-actions@github.com'") + os.system("git add data.json") + os.system("git commit -m 'Update outage data'") + os.system("git push") if __name__ == '__main__': main() + +""" +curl ^"https://uiapi2.saapa.ir/api/ebills/PlannedBlackoutsReport^" ^ + --compressed ^ + -X POST ^ + -H ^"Authorization: Bearer ...^" ^ + --data-raw ^"{\"bill_id\":\"7619314604429\",\"from_date\":\"1404/03/11\",\"to_date\":\"1404/03/16\"}^" +""" diff --git a/requirements.txt b/requirements.txt index a98ae43..246d8c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ requests +jdatetime beautifulsoup4 \ No newline at end of file diff --git a/site-version.py b/site-version.py new file mode 100644 index 0000000..b17d5c0 --- /dev/null +++ b/site-version.py @@ -0,0 +1,95 @@ +import os +import re +import time +import requests +from bs4 import BeautifulSoup + +token = os.getenv("EITAAYAR_TOKEN") +chat_id = os.getenv("CHAT_ID") + +if not token: + raise EnvironmentError("EITAAYAR_TOKEN is not set!") + +if not chat_id: + raise EnvironmentError("CHAT_ID is not set!") + + +def send_message(text: str) -> dict: + sent_at: int = int(time.time()) + url = f'https://eitaayar.ir/api/{token}/sendMessage?chat_id={chat_id}&text={text}&title={sent_at=}' + return requests.get(url).json() + + +def get_blockout_page() -> str: + blockout_link = 'https://qepd.co.ir/fa-IR/DouranPortal/6423' + blockout_link = 'https://re.rodad.net/blockout' + return requests.get(blockout_link).text + + +def convert_to_english_numbers(text): + persian_to_english = str.maketrans("۰۱۲۳۴۵۶۷۸۹", "0123456789") + return text.translate(persian_to_english) + + +def find_times(text: str) -> list[str]: + text = convert_to_english_numbers(text) + pattern = r"(\d{1,2}:\d{2}|\d{1,2})" + return re.findall(pattern, text) + +def is_time_past(time_str: str) -> bool: + try: + current_time = datetime.now(iran_tz).time() + + if ":" in time_str: + time_obj = datetime.strptime(time_str.strip(), "%H:%M").time() + else: + time_obj = datetime.strptime(time_str.strip(), "%H").time() + + return time_obj < current_time + except Exception: + return false + +def make_message(html: str) -> str|None: + return None + if len(html) == 0: + return "خطا در خواندن صفحه!" + + soup = BeautifulSoup(html, 'html.parser') + # table = soup.find('table', id='ctl01_ctl00_myDataList') + + block_needle = 'بلوک A4' + try: + paragraphs = soup.find_all('p') + block = soup.find('p', string=lambda text: isinstance(text, str) and block_needle in text) + time_index = paragraphs.index(block) - 1 + text = paragraphs[time_index].get_text(separator='\n', strip=True) + start, end, *_ = find_times(text) + + if is_time_past(start): + return None + + return text + except: + return f"اطلاعات {block_needle} یافت نشد!" + + +def main() -> None: + try: + page = get_blockout_page() + message = make_message(page) + except requests.exceptions.Timeout: + message = 'درخواست ارسال نشد!' + + if not message: + return None + + response = send_message(message) + if not response.get('ok'): + if response.get('description'): + raise Exception(response.get('description')) + else: + raise Exception('something sent wrong!') + + +if __name__ == '__main__': + main()