fix again
This commit is contained in:
10
newpower.py
10
newpower.py
@@ -16,11 +16,11 @@ from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
|||||||
import get_rpc_config_auto
|
import get_rpc_config_auto
|
||||||
|
|
||||||
# Import provider classes
|
# Import provider classes
|
||||||
from base import BaseCountyProvider
|
from providers.base import BaseCountyProvider
|
||||||
from kubra import KubraCountyProvider
|
from providers.kubra import KubraCountyProvider
|
||||||
from simple import SimpleCountyJsonProvider
|
from providers.simple import SimpleCountyJsonProvider
|
||||||
from nisc import NiscCountyProvider
|
from providers.nisc import NiscCountyProvider
|
||||||
from gwt_rpc import GwtRpcCountyProvider
|
from providers.gwt_rpc import GwtRpcCountyProvider
|
||||||
|
|
||||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||||
|
|
||||||
|
|||||||
10
newpower2.py
10
newpower2.py
@@ -19,11 +19,11 @@ from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
|||||||
import get_rpc_config_auto
|
import get_rpc_config_auto
|
||||||
|
|
||||||
# Import provider classes
|
# Import provider classes
|
||||||
from base import BaseProvider
|
from providers.base import BaseProvider
|
||||||
from kubra import KubraProvider
|
from providers.kubra import KubraProvider
|
||||||
from simple import SimpleJsonProvider
|
from providers.simple import SimpleJsonProvider
|
||||||
from gwt_rpc import GwtRpcProvider
|
from providers.gwt_rpc import GwtRpcProvider
|
||||||
from nisc import NiscHostedProvider
|
from providers.nisc import NiscHostedProvider
|
||||||
|
|
||||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||||
|
|
||||||
|
|||||||
BIN
providers/__pycache__/base.cpython-310.pyc
Normal file
BIN
providers/__pycache__/base.cpython-310.pyc
Normal file
Binary file not shown.
BIN
providers/__pycache__/gwt_rpc.cpython-310.pyc
Normal file
BIN
providers/__pycache__/gwt_rpc.cpython-310.pyc
Normal file
Binary file not shown.
BIN
providers/__pycache__/kubra.cpython-310.pyc
Normal file
BIN
providers/__pycache__/kubra.cpython-310.pyc
Normal file
Binary file not shown.
BIN
providers/__pycache__/nisc.cpython-310.pyc
Normal file
BIN
providers/__pycache__/nisc.cpython-310.pyc
Normal file
Binary file not shown.
BIN
providers/__pycache__/simple.cpython-310.pyc
Normal file
BIN
providers/__pycache__/simple.cpython-310.pyc
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@ from urllib.parse import urlparse
|
|||||||
from pyproj import Transformer
|
from pyproj import Transformer
|
||||||
|
|
||||||
import get_rpc_config_auto
|
import get_rpc_config_auto
|
||||||
from base import BaseProvider, BaseCountyProvider
|
from providers.base import BaseProvider, BaseCountyProvider
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -43,13 +43,12 @@ class GwtRpcBaseProvider:
|
|||||||
|
|
||||||
logger.info(f"Attempting Auto-Repair for {self.name}...")
|
logger.info(f"Attempting Auto-Repair for {self.name}...")
|
||||||
try:
|
try:
|
||||||
# This function needs to be defined in the main script context to save config
|
# This function needs to be defined in the main script context to save config.
|
||||||
from newpower import update_provider_config as update_county_config
|
# We import it here, inside the method, to avoid circular import errors at startup.
|
||||||
except ImportError:
|
if isinstance(self, GwtRpcCountyProvider):
|
||||||
from newpower2 import update_provider_config as update_point_config
|
from newpower import update_provider_config
|
||||||
update_county_config = update_point_config # Fallback
|
else:
|
||||||
|
from newpower2 import update_provider_config
|
||||||
try:
|
|
||||||
_, valid_headers, valid_cookies, valid_body = get_rpc_config_auto.fetch_live_data(self.map_url)
|
_, valid_headers, valid_cookies, valid_body = get_rpc_config_auto.fetch_live_data(self.map_url)
|
||||||
if valid_headers and valid_body:
|
if valid_headers and valid_body:
|
||||||
logger.info(f"Repair successful! Updating {self.name}.")
|
logger.info(f"Repair successful! Updating {self.name}.")
|
||||||
@@ -72,7 +71,7 @@ class GwtRpcBaseProvider:
|
|||||||
self.session.cookies.set(cookie['name'], cookie['value'], domain=cookie['domain'], path=cookie['path'])
|
self.session.cookies.set(cookie['name'], cookie['value'], domain=cookie['domain'], path=cookie['path'])
|
||||||
|
|
||||||
# Save to disk for next time
|
# Save to disk for next time
|
||||||
update_county_config(self.name, self.config)
|
update_provider_config(self.name, self.config)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Auto-repair failed: {e}")
|
logger.error(f"Auto-repair failed: {e}")
|
||||||
@@ -4,7 +4,7 @@ import logging
|
|||||||
import polyline
|
import polyline
|
||||||
import mercantile
|
import mercantile
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from base import BaseProvider, BaseCountyProvider
|
from providers.base import BaseProvider, BaseCountyProvider
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from pyproj import Transformer
|
from pyproj import Transformer
|
||||||
from base import BaseProvider, BaseCountyProvider
|
from providers.base import BaseProvider, BaseCountyProvider
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from base import BaseProvider, BaseCountyProvider
|
from providers.base import BaseProvider, BaseCountyProvider
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
163
test.py
163
test.py
@@ -1,163 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
|
|
||||||
def decode_gwt_rpc(payload):
|
|
||||||
"""
|
|
||||||
Decodes a GWT-RPC payload to extract outage data for Counties.
|
|
||||||
"""
|
|
||||||
# 1. Clean the payload
|
|
||||||
# GWT responses often start with //OK. We strip that.
|
|
||||||
if payload.startswith("//OK"):
|
|
||||||
payload = payload[4:]
|
|
||||||
|
|
||||||
# 2. Parse the FULL payload as JSON
|
|
||||||
# The GWT payload is structurally a JSON array: [stream_data..., [string_table], flags...]
|
|
||||||
try:
|
|
||||||
full_data = json.loads(payload)
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
print(f"Error parsing payload JSON: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
# 3. Separate Stream and String Table
|
|
||||||
# The String Table is a list of strings located near the end of the main array.
|
|
||||||
# The "Stream" is everything before that string table.
|
|
||||||
|
|
||||||
string_table = None
|
|
||||||
stream_raw = []
|
|
||||||
|
|
||||||
# Iterate through the parsed array to find the string table (which is a list)
|
|
||||||
for item in full_data:
|
|
||||||
if isinstance(item, list):
|
|
||||||
string_table = item
|
|
||||||
# Once we find the table, we assume the rest are flags and stop adding to stream
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
stream_raw.append(item)
|
|
||||||
|
|
||||||
if not string_table:
|
|
||||||
print("Error: String table not found in payload.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
# 4. Normalize the Stream
|
|
||||||
# The decoder logic relies on integers (1-based indices).
|
|
||||||
# The raw stream might contain floats or strings that we need to cast or filter.
|
|
||||||
stream = []
|
|
||||||
for token in stream_raw:
|
|
||||||
if isinstance(token, int):
|
|
||||||
stream.append(token)
|
|
||||||
elif isinstance(token, float):
|
|
||||||
stream.append(int(token))
|
|
||||||
elif isinstance(token, str):
|
|
||||||
# Sometimes numeric values are sent as strings in the stream
|
|
||||||
try:
|
|
||||||
stream.append(int(float(token)))
|
|
||||||
except ValueError:
|
|
||||||
# If it's a non-numeric string token (like a cache ID), ignore it
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 5. Decode Logic
|
|
||||||
try:
|
|
||||||
# Define the signatures we are looking for in the String Table
|
|
||||||
REGION_SIG = "cc.nisc.oms.clientandserver.v2.pojo.Region/3192921568"
|
|
||||||
INTEGER_SIG = "java.lang.Integer/3438268394"
|
|
||||||
CATEGORY_KEY = "County"
|
|
||||||
|
|
||||||
# Helper to find 1-based index
|
|
||||||
def get_index(val):
|
|
||||||
try: return string_table.index(val) + 1
|
|
||||||
except ValueError: return 0
|
|
||||||
|
|
||||||
region_type_id = get_index(REGION_SIG)
|
|
||||||
integer_type_id = get_index(INTEGER_SIG)
|
|
||||||
county_type_id = get_index(CATEGORY_KEY)
|
|
||||||
|
|
||||||
if region_type_id == 0:
|
|
||||||
print("Error: Region type signature not found in string table.")
|
|
||||||
# Debug: Print first few strings to verify if signatures changed
|
|
||||||
# print("Available strings:", string_table[:10])
|
|
||||||
return None
|
|
||||||
|
|
||||||
results = []
|
|
||||||
i = 0
|
|
||||||
stream_len = len(stream)
|
|
||||||
|
|
||||||
# Iterate through the stream looking for Region objects
|
|
||||||
while i < stream_len:
|
|
||||||
if stream[i] == region_type_id:
|
|
||||||
try:
|
|
||||||
# We found a Region. The next few integers define its properties.
|
|
||||||
# Pointer 'p' is relative to current index 'i'
|
|
||||||
p = i + 1
|
|
||||||
|
|
||||||
# --- Field 1: Total Served ---
|
|
||||||
# Logic: Value is valid if followed by Integer Type ID
|
|
||||||
served = 0
|
|
||||||
val1 = stream[p]
|
|
||||||
p += 1
|
|
||||||
if p < stream_len and stream[p] == integer_type_id:
|
|
||||||
served = val1
|
|
||||||
p += 1 # Skip type ID
|
|
||||||
|
|
||||||
# --- Field 2: Number Out ---
|
|
||||||
out = 0
|
|
||||||
val2 = stream[p]
|
|
||||||
p += 1
|
|
||||||
if p < stream_len and stream[p] == integer_type_id:
|
|
||||||
out = val2
|
|
||||||
p += 1 # Skip type ID
|
|
||||||
|
|
||||||
# --- Field 3: Name Index ---
|
|
||||||
name_idx = stream[p]
|
|
||||||
p += 1
|
|
||||||
|
|
||||||
# --- Field 4: Category Index ---
|
|
||||||
cat_idx = stream[p]
|
|
||||||
|
|
||||||
# Check if this is a County
|
|
||||||
if cat_idx == county_type_id:
|
|
||||||
name = "Unknown"
|
|
||||||
if 0 < name_idx <= len(string_table):
|
|
||||||
name = string_table[name_idx - 1]
|
|
||||||
|
|
||||||
percent = 0.0
|
|
||||||
if served > 0:
|
|
||||||
percent = (out / served) * 100
|
|
||||||
|
|
||||||
results.append({
|
|
||||||
"county": name,
|
|
||||||
"served": served,
|
|
||||||
"out": out,
|
|
||||||
"percent": percent
|
|
||||||
})
|
|
||||||
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error during stream traversal: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
filename = "outage_data.txt"
|
|
||||||
if os.path.exists(filename):
|
|
||||||
with open(filename, "r", encoding="utf-8") as f:
|
|
||||||
raw_content = f.read().strip()
|
|
||||||
|
|
||||||
data = decode_gwt_rpc(raw_content)
|
|
||||||
|
|
||||||
if data:
|
|
||||||
# Sort A-Z
|
|
||||||
data.sort(key=lambda x: x['county'])
|
|
||||||
|
|
||||||
print(f"{'County':<20} | {'Served':>8} | {'Out':>8} | {'Percent':>8}")
|
|
||||||
print("-" * 55)
|
|
||||||
for row in data:
|
|
||||||
print(f"{row['county']:<20} | {row['served']:>8} | {row['out']:>8} | {row['percent']:>7.2f}%")
|
|
||||||
else:
|
|
||||||
print("No data found.")
|
|
||||||
else:
|
|
||||||
print(f"File '{filename}' not found. Please create it and paste the payload.")
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user