1+ #!/bin/env python3
2+
3+ import requests
4+ import pymysql
5+ import json
6+ import scrtsxx
7+
8+ VERSION = 20250319.1444
9+
10+ class BusurExitIP ():
11+ def connDB (self ):
12+
13+ self .db = pymysql .connect (host = scrtsxx .HOST ,
14+ port = scrtsxx .PORT ,
15+ user = scrtsxx .USERNAME ,
16+ passwd = scrtsxx .PASSWORD ,
17+ db = scrtsxx .DB ,
18+ charset = "utf8mb4" ,
19+ cursorclass = pymysql .cursors .DictCursor
20+ )
21+
22+ def upsert_nodes (self , node_data ):
23+ cursor = self .db .cursor ()
24+
25+ query = """
26+ INSERT INTO exitip (
27+ addr, moniker, version, type, api, exitIp, asn, continentCode, countryCode, country,
28+ city, latitude, longitude, ipRep, isResidential, isActive, isHealthy, isDuplicate,
29+ isWhitelisted, fetchedAt, inactiveAt
30+ ) VALUES (
31+ %(addr)s, %(moniker)s, %(version)s, %(type)s, %(api)s, %(exitIp)s, %(asn)s,
32+ %(continentCode)s, %(countryCode)s, %(country)s, %(city)s, %(latitude)s,
33+ %(longitude)s, %(ipRep)s, %(isResidential)s, %(isActive)s, %(isHealthy)s,
34+ %(isDuplicate)s, %(isWhitelisted)s, %(fetchedAt)s, %(inactiveAt)s
35+ )
36+ ON DUPLICATE KEY UPDATE
37+ moniker = VALUES(moniker),
38+ version = VALUES(version),
39+ api = VALUES(api),
40+ exitIp = VALUES(exitIp),
41+ asn = VALUES(asn),
42+ continentCode = VALUES(continentCode),
43+ countryCode = VALUES(countryCode),
44+ country = VALUES(country),
45+ city = VALUES(city),
46+ latitude = VALUES(latitude),
47+ longitude = VALUES(longitude),
48+ ipRep = VALUES(ipRep),
49+ isResidential = VALUES(isResidential),
50+ isActive = VALUES(isActive),
51+ isHealthy = VALUES(isHealthy),
52+ isDuplicate = VALUES(isDuplicate),
53+ isWhitelisted = VALUES(isWhitelisted),
54+ fetchedAt = VALUES(fetchedAt),
55+ inactiveAt = VALUES(inactiveAt)
56+ """
57+
58+ # Convert booleans to integers (MySQL TINYINT)
59+ for node in node_data :
60+ node ['isResidential' ] = 1 if node ['isResidential' ] else 0
61+ node ['isActive' ] = 1 if node ['isActive' ] else 0
62+ node ['isHealthy' ] = 1 if node ['isHealthy' ] else 0
63+ node ['isDuplicate' ] = 1 if node ['isDuplicate' ] else 0
64+ node ['isWhitelisted' ] = 1 if node ['isWhitelisted' ] else 0
65+
66+ if node ['inactiveAt' ] is None :
67+ node ['inactiveAt' ] = None
68+
69+
70+ cursor .executemany (query , node_data )
71+ self .db .commit ()
72+ print (f"{ cursor .rowcount } records affected" )
73+ self .db .close ()
74+
75+
76+
77+ if __name__ == "__main__" :
78+
79+ header = {"partnerKey" : scrtsxx .BUSUR_KEY }
80+ busur = BusurExitIP ()
81+ busur .connDB ()
82+
83+ try :
84+ response = requests .get (scrtsxx .BUSUR , headers = header )
85+ response .raise_for_status ()
86+
87+ data = response .json ()
88+ if data .get ('success' ) and data .get ('data' ):
89+ nodes = data ['data' ]
90+ busur .upsert_nodes (nodes )
91+ else :
92+ print ("Invalid response format" )
93+
94+ except requests .exceptions .RequestException as e :
95+ print (f"API Request Failed: { e } " )
0 commit comments