Selaa lähdekoodia

ip解析,获取天气兼容GeoIP2和OpenWeatherMap服务

locky 1 vuosi sitten
vanhempi
commit
c7fd23688f

+ 2 - 2
Controller/DeviceConfirmRegion.py

@@ -26,7 +26,7 @@ class ConfirmRegion(View):
             device_domain_qs = DeviceDomainModel.objects.filter(ip=ip)
 
             # 获取国家编码
-            ip_addr_qs = IPAddr.objects.filter(ip=ip).values('country_code')
+            ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False).values('country_code')
             if ip_addr_qs.exists():
                 country_code = ip_addr_qs[0]['country_code']
             else:
@@ -93,7 +93,7 @@ class ConfirmRegionV2(View):
             data_dict['ip'] = ip
 
             # 获取国家编码
-            ip_addr_qs = IPAddr.objects.filter(ip=ip).values('country_code')
+            ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False).values('country_code')
             if ip_addr_qs.exists():
                 country_code = ip_addr_qs[0]['country_code']
             else:

+ 55 - 22
Controller/ShadowController.py

@@ -3,12 +3,12 @@ import time
 
 from django.http import JsonResponse
 
-from Ansjer.config import SERVER_TYPE, LOGGER
-from Model.models import Device_Info, UidSetModel, UID_Preview, VoicePromptModel, UID_Bucket, UidChannelSetModel, \
+from Ansjer.config import SERVER_TYPE, LOGGER, CONFIG_INFO, CONFIG_CN
+from Model.models import Device_Info, UidSetModel, UID_Preview, VoicePromptModel, UidChannelSetModel, \
     AiService, CountryModel, CityInformation, IPAddr
 from Object.ETkObject import ETkObject
 from Service.CommonService import CommonService
-from Object.IPWeatherObject import IPQuery
+from Object.IPWeatherObject import IPQuery, GeoIP2
 
 
 # 更新设备影子
@@ -66,17 +66,8 @@ def update_device_shadow(request):
             AiService.objects.filter(uid=uid, use_status=1).update(detect_status=0, detect_group='')
             LOGGER.info('{}v2重置成功'.format(uid))
 
-            # 和新ip的city_id不一致,更新tb_city_information_id
-            uid_set_qs = UidSetModel.objects.filter(uid=uid).values('ip', 'tb_city_information_id')
-            if uid_set_qs.exists():
-                # 查询ip区级信息
-                district = get_district(ip)
-
-                city_information_qs = CityInformation.objects.filter(district=district).values('city_id')
-                if city_information_qs.exists():
-                    city_id = city_information_qs[0]['city_id']
-                    if uid_set_qs[0]['tb_city_information_id'] != city_id:
-                        uid_set_qs.update(tb_city_information_id=city_id)
+            # 更新ip信息
+            update_ip_info(ip, uid)
 
         ucode = request_dict.get('ucode', None)
         version = request_dict.get('version', None)
@@ -144,13 +135,7 @@ def update_device_shadow(request):
             qs_dict['tb_country'] = country
         LOGGER.info('{} qs_dict: {}'.format(uid, qs_dict))
 
-        # 查询ip区级信息
-        district = get_district(ip)
-
-        city_information_qs = CityInformation.objects.filter(district=district).values('city_id')
-        if city_information_qs.exists():
-            city_id = city_information_qs[0]['city_id']
-            qs_dict['tb_city_information_id'] = city_id
+        save_ip_info(ip, qs_dict)
 
         us_qs = UidSetModel.objects.filter(uid=uid)
         if us_qs.exists():
@@ -171,8 +156,56 @@ def update_device_shadow(request):
         return JsonResponse(status=200, data={'code': 1000001, 'update_shadow_error': repr(e)})
 
 
+def save_ip_info(ip, qs_dict):
+    """
+    保存ip信息
+    根据服务器配置使用不同的服务, 国内:阿里云, 测试,国外:geoip2
+    @param ip:
+    @param qs_dict:
+    @return:
+    """
+    if CONFIG_INFO == CONFIG_CN:
+        # 查询ip区级信息
+        district = get_district(ip)
+
+        city_information_qs = CityInformation.objects.filter(district=district).values('city_id')
+        if city_information_qs.exists():
+            city_id = city_information_qs[0]['city_id']
+            qs_dict['tb_city_information_id'] = city_id
+    else:
+        ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=True)
+        if not ip_addr_qs.exists():
+            GeoIP2(ip)
+
+
+def update_ip_info(ip, uid):
+    """
+    更新ip信息
+    根据服务器配置使用不同的服务, 国内:阿里云, 测试,国外:geoip2
+    @param ip:
+    @param uid:
+    @return:
+    """
+    if CONFIG_INFO == CONFIG_CN:
+        # 和新ip的city_id不一致,更新tb_city_information_id
+        uid_set_qs = UidSetModel.objects.filter(uid=uid).values('ip', 'tb_city_information_id')
+        if uid_set_qs.exists():
+            # 查询ip区级信息
+            district = get_district(ip)
+
+            city_information_qs = CityInformation.objects.filter(district=district).values('city_id')
+            if city_information_qs.exists():
+                city_id = city_information_qs[0]['city_id']
+                if uid_set_qs[0]['tb_city_information_id'] != city_id:
+                    uid_set_qs.update(tb_city_information_id=city_id)
+    else:
+        ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=True)
+        if not ip_addr_qs.exists():
+            GeoIP2(ip)
+
+
 def get_district(ip):
-    ip_addr_qs = IPAddr.objects.filter(ip=ip).values('district', 'city')
+    ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False).values('district', 'city')
     if ip_addr_qs.exists():
         district = ip_addr_qs[0]['district']
         if district == '':

+ 9 - 1
Controller/TestApi.py

@@ -51,7 +51,7 @@ from Model.models import (
 from Object.AliPayObject import AliPayObject
 from Object.AWS.AmazonS3Util import AmazonS3Util
 from Object.ContentSecurityObject import ContentSecurity
-from Object.IPWeatherObject import IPQuery, OpenWeatherMap
+from Object.IPWeatherObject import IPQuery, OpenWeatherMap, GeoIP2
 from Object.m3u8generate import PlaylistGenerator
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
@@ -161,6 +161,8 @@ class testView(View):
             return self.convertTimestamp(request_dict, response)
         elif operation == 'checkOrderExist':  # 检查paypal订单是否存在
             return self.checkOrderExist(request_dict, response)
+        elif operation == 'foreignIp':  # 查询外国ip
+            return self.foreignIp(request_dict, response)
         elif operation == 'getForeignWeather':  # 获取外国天气
             return self.getForeignWeather(request_dict, response)
         else:
@@ -1108,6 +1110,12 @@ class testView(View):
         except Exception as e:
             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
+    @staticmethod
+    def foreignIp(request_dict, response):
+        ip = request_dict.get('ip', None)
+        ip_obj = GeoIP2(ip)
+        return response.json(0)
+
     @staticmethod
     def getForeignWeather(request_dict, response):
         lat = float(request_dict.get('lat', None))

+ 38 - 25
Controller/WeatherControl.py

@@ -6,12 +6,10 @@
 """
 import datetime
 
-from Ansjer.config import LOGGER
-import time
-
+from Ansjer.config import CONFIG_INFO, CONFIG_CN
 from django.views import View
-from Object.IPWeatherObject import WeatherInfo
-from Model.models import UidSetModel, CityInformation
+from Object.IPWeatherObject import WeatherInfo, OpenWeatherMap
+from Model.models import UidSetModel, IPAddr
 from Object.ResponseObject import ResponseObject
 from Object.RedisObject import RedisObject
 from Service.CommonService import CommonService
@@ -21,14 +19,14 @@ class WeatherView(View):
     def get(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
         operation = kwargs.get('operation')
-        return self.validation(request.GET, operation, request)
+        return self.validation(request.GET, operation)
 
     def post(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
         operation = kwargs.get('operation')
-        return self.validation(request.POST, operation, request)
+        return self.validation(request.POST, operation)
 
-    def validation(self, request_dict, operation, request):
+    def validation(self, request_dict, operation):
         lang = request_dict.get('lang', 'en')
         response = ResponseObject(lang)
         if operation == 'get':  # 获取天气
@@ -48,27 +46,42 @@ class WeatherView(View):
         uid = request_dict.get('uid')
         if not uid:
             return response.json(444, 'uid')
-        uid_set_qs = UidSetModel.objects.filter(uid=uid).values('tb_city_information_id')
+
+        uid_set_qs = UidSetModel.objects.filter(uid=uid).values('tb_city_information_id', 'ip')
         if not uid_set_qs.exists():
             return response.json(173)
-        redis_obj = RedisObject()
-        city_id = uid_set_qs[0]['tb_city_information_id']
-        if city_id == 0:
-            return response.json(10, '请更新设备影子地区信息')
-        today = datetime.datetime.today()
-        now_time = datetime.datetime(today.year, today.month, today.day, today.hour)
-        time_stamp = CommonService.str_to_timestamp(now_time.strftime('%Y-%m-%d %H:%M:%S'))
+
         try:
-            weather = redis_obj.get_data('city_id_{}_{}_weather'.format(city_id, time_stamp))
-            if weather:
-                temp, humidity = weather.split('/')
+            # 根据服务器配置使用不同的服务, 国内:阿里云墨迹天气, 测试,国外:OpenWeatherMap
+            if CONFIG_INFO == CONFIG_CN:
+                city_id = uid_set_qs[0]['tb_city_information_id']
+                if city_id == 0:
+                    return response.json(10, '请更新设备影子地区信息')
+
+                today = datetime.datetime.today()
+                now_time = datetime.datetime(today.year, today.month, today.day, today.hour)
+                time_stamp = CommonService.str_to_timestamp(now_time.strftime('%Y-%m-%d %H:%M:%S'))
+                key = 'city_id_{}_{}_weather'.format(city_id, time_stamp)
+
+                redis_obj = RedisObject()
+                weather = redis_obj.get_data(key)
+                if weather:
+                    temp, humidity = weather.split('/')
+                else:
+                    city_obj = WeatherInfo(city_id)
+                    temp, humidity = city_obj.get_city_weather()
+                    if temp and humidity:
+                        redis_obj.set_ex_data(key, '{}/{}'.format(temp, humidity), 3600)
             else:
-                city_obj = WeatherInfo(city_id)
-                temp, humidity = city_obj.get_city_weather()
-                if temp and humidity:
-                    redis_obj.set_ex_data('city_id_{}_{}_weather'.format(city_id, time_stamp),
-                                          '{}/{}'.format(temp, humidity), 3600)
-            if not all([temp, humidity]):
+                ip = uid_set_qs[0]['ip']
+                ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=True).values('lat', 'lon')
+                if not ip_addr_qs.exists():
+                    return response.json(173)
+                lat, lon = ip_addr_qs[0]['lat'], ip_addr_qs[0]['lon']
+                open_weather_map = OpenWeatherMap(lat, lon)
+                temp, humidity = open_weather_map.get_weather()
+
+            if temp is None and humidity is None:
                 return response.json(10, '获取天气失败')
             return response.json(0, {'temp': temp, 'humidity': humidity})
         except Exception as e:

+ 60 - 8
Object/IPWeatherObject.py

@@ -1,10 +1,14 @@
 # @Author    : Rocky
 # @File      : IPWeatherObject.py
 # @Time      : 2023/8/16 8:56
+import datetime
+
 import geoip2.webservice
 import requests
 
 from Model.models import IPAddr
+from Object.RedisObject import RedisObject
+from Service.CommonService import CommonService
 
 
 class IPQuery:
@@ -43,7 +47,7 @@ class IPQuery:
                     city += '市'
 
                 # ip地址信息存表或更新
-                ip_addr_qs = IPAddr.objects.filter(ip=ip)
+                ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False)
                 if ip_addr_qs.exists():
                     ip_addr_qs.update(district=district, city=city, region=region, country_code=country_id)
                 else:
@@ -95,17 +99,42 @@ class WeatherInfo:
 class GeoIP2:
     """
     MaxMind GeoIP2查询国外ip
+    同时保存ip信息
     https://www.maxmind.com/
     """
 
     def __init__(self, ip):
-        self.account_id = 0
-        self.license_key = ''
-        with geoip2.webservice.Client(self.account_id, self.license_key) as client:
-            # You can also use `client.city` or `client.insights`
-            # `client.insights` is not available to GeoLite2 users
-            response = client.country(ip)
-            print(response.country.iso_code)
+        self.account_id = 938644
+        self.license_key = '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'
+        self.license_key_sandbox = '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'
+
+        try:
+            with geoip2.webservice.Client(self.account_id, self.license_key) as client:
+                # You can also use `client.city` or `client.insights`
+                # `client.insights` is not available to GeoLite2 users
+                response = client.city(ip)
+
+                # 经纬度精确到小数点两位
+                lat = round(response.location.latitude, 2)
+                lon = round(response.location.longitude, 2)
+                city = response.city.names['zh-CN']
+                region = response.subdivisions[0].names['zh-CN']
+                country_code = response.country.iso_code
+
+                # 保存ip信息
+                ip_addr_data = {
+                    'ip': ip,
+                    'lat': lat,
+                    'lon': lon,
+                    'city': city,
+                    'region': region,
+                    'country_code': country_code,
+                    'is_geoip2': True
+                }
+                IPAddr.objects.create(**ip_addr_data)
+
+        except Exception as e:
+            print('error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
 
 class OpenWeatherMap:
@@ -119,6 +148,29 @@ class OpenWeatherMap:
         self.lat = lat  # 纬度
         self.lon = lon  # 经度
 
+    def get_weather(self):
+        """
+        从缓存查询天气数据
+        或者查询当前天气,并缓存数据
+        @return: temp, humidity
+        """
+        # 查询缓存数据
+        today = datetime.datetime.today()
+        now_time = datetime.datetime(today.year, today.month, today.day, today.hour)
+        time_stamp = CommonService.str_to_timestamp(now_time.strftime('%Y-%m-%d %H:%M:%S'))
+        key = 'weather:lat:{}_lon:{}_time_stamp:{}'.format(self.lat, self.lon, time_stamp)
+
+        redis_obj = RedisObject()
+        weather = redis_obj.get_data(key)
+        if weather:
+            temp, humidity = weather.split('/')
+        else:
+            temp, humidity = self.get_current_weather()
+            if temp is not None and humidity is not None:
+                key = 'weather:lat:{}_lon:{}_time_stamp:{}'.format(self.lat, self.lon, time_stamp)
+                redis_obj.set_ex_data(key, '{}/{}'.format(temp, humidity), 3600)
+        return temp, humidity
+
     def get_current_weather(self):
         """
         根据经纬度获取当前天气