- Регистрация
- 22.03.2019
- Сообщения
- 2 014
- Благодарностей
- 1 435
- Баллы
- 113
Intro
Начиная с версии 7.8.13.0 вместе с Зеннопостером нам дают еще и геобазу в формате MaxMind. Не знаю для кого как, а для меня это новая фишка от ZennoLab прям имба.
Если кто-то вместе с прокси устанавлвиает таймзону и геопозицию автоматом, то я люблю это делать в ручную, что бы контролировать что куда ставится и ставится ли вообще. А с получением координат можно еще и на ZennoBrowser их натянуть, играясь с погрешностью и т.д.
Если раньше я выполнял дополнительный запрос для получения таймзоны или координат к разным глючным сервисам, которые грешать таймаутами, лимитами и т.д., то сейчас это все кануло в лета.
Может и для кого-то из разработчиков это будет полезно.
Дисклеймер: Спасибо что у нас всех появился новый помощник - ГПТ, используя системпромт пишет код который почти сразу же работает в зенке.
Приступим к реализации:
1. Для начала я нашел где лежит геобаза, в 99% случаях это: %user%\AppData\Roaming\ZennoLab\ZennoPoster\7\Data\GeoLite2-City.mmdb
2. Сам код копируем в "Общий код":
3. Вызываем код:
3.1. Если база лежит в ином месте:
Вызвав наш код мы получаем во вкладке "Json" данные по IP. Так же, можно вернуть дынные в переменные если есть в этом необходимость.
Надеюсь данное решение для вас будет полезным.
Ставьте спасибо и голос за работу
Начиная с версии 7.8.13.0 вместе с Зеннопостером нам дают еще и геобазу в формате MaxMind. Не знаю для кого как, а для меня это новая фишка от ZennoLab прям имба.
Если кто-то вместе с прокси устанавлвиает таймзону и геопозицию автоматом, то я люблю это делать в ручную, что бы контролировать что куда ставится и ставится ли вообще. А с получением координат можно еще и на ZennoBrowser их натянуть, играясь с погрешностью и т.д.
Если раньше я выполнял дополнительный запрос для получения таймзоны или координат к разным глючным сервисам, которые грешать таймаутами, лимитами и т.д., то сейчас это все кануло в лета.
Может и для кого-то из разработчиков это будет полезно.
Дисклеймер: Спасибо что у нас всех появился новый помощник - ГПТ, используя системпромт пишет код который почти сразу же работает в зенке.
Приступим к реализации:
1. Для начала я нашел где лежит геобаза, в 99% случаях это: %user%\AppData\Roaming\ZennoLab\ZennoPoster\7\Data\GeoLite2-City.mmdb
2. Сам код копируем в "Общий код":
C#:
namespace Geo
{
public static class GeoLite2
{
private static readonly byte[] Marker = new byte[] { 0xAB, 0xCD, 0xEF, 0x4D, 0x61, 0x78, 0x4D, 0x69, 0x6E, 0x64, 0x2E, 0x63, 0x6F, 0x6D };
public static string Lookup(string ipAddress, string dbPath = @"C:\Users\user\AppData\Roaming\ZennoLab\ZennoPoster\7\Data\GeoLite2-City.mmdb")
{
if (string.IsNullOrEmpty(ipAddress)) return null;
System.Net.IPAddress parsedIp;
if (!System.Net.IPAddress.TryParse(ipAddress, out parsedIp)) return null;
byte[] ipBytes = parsedIp.GetAddressBytes();
if (ipBytes.Length == 4)
{
byte[] tmp = new byte[16];
tmp[10] = tmp[11] = 0xff;
Array.Copy(ipBytes, 0, tmp, 12, 4);
ipBytes = tmp;
}
byte[] f = System.IO.File.ReadAllBytes(dbPath);
int ms = -1;
for (int i = f.Length - Marker.Length; i >= 0; i--)
{
bool ok = true;
for (int j = 0; j < Marker.Length && ok; j++) ok = f[i + j] == Marker[j];
if (ok) { ms = i + Marker.Length; break; }
}
if (ms < 0) return null;
int mo = ms;
var meta = RMap(f, ref mo, ms);
int nc = Convert.ToInt32(meta["node_count"]);
int rs = Convert.ToInt32(meta["record_size"]);
int ds = nc * rs * 2 / 8 + 16;
int node = 0;
for (int i = 0; i < 128 && node < nc; i++)
{
int bit = (ipBytes[i / 8] >> (7 - (i % 8))) & 1;
int no = node * rs * 2 / 8;
int rec = rs == 24 ? (bit == 0 ? (f[no] << 16) | (f[no + 1] << 8) | f[no + 2] : (f[no + 3] << 16) | (f[no + 4] << 8) | f[no + 5])
: rs == 28 ? (bit == 0 ? ((f[no + 3] & 0xF0) << 20) | (f[no] << 16) | (f[no + 1] << 8) | f[no + 2] : ((f[no + 3] & 0x0F) << 24) | (f[no + 4] << 16) | (f[no + 5] << 8) | f[no + 6])
: (bit == 0 ? (f[no] << 24) | (f[no + 1] << 16) | (f[no + 2] << 8) | f[no + 3] : (f[no + 4] << 24) | (f[no + 5] << 16) | (f[no + 6] << 8) | f[no + 7]);
if (rec == nc) return null;
if (rec > nc)
{
int off = (rec - nc) + ds - 16;
var d = RVal(f, ref off, ds) as Dictionary<string, object>;
if (d == null) return null;
string cc = GS(d, "country", "iso_code"), cn = GL(d, "country", "names"), cy = GL(d, "city", "names");
string lat = GD(d, "location", "latitude"), lon = GD(d, "location", "longitude"), tz = GS(d, "location", "time_zone");
return "{" +
"\"country_code\":\"" + Esc(cc) + "\"," +
"\"country_name\":\"" + Esc(cn) + "\"," +
"\"city_name\":\"" + Esc(cy) + "\"," +
"\"latitude\":\"" + lat + "\"," +
"\"longitude\":\"" + lon + "\"," +
"\"timezone\":\"" + Esc(tz) + "\"" +
"}";
}
node = rec;
}
return null;
}
private static string Esc(string s) { return s == null ? "" : s.Replace("\\", "\\\\").Replace("\"", "\\\""); }
private static object RVal(byte[] b, ref int p, int dss)
{
int c = b[p++], t = c >> 5;
if (t == 0) t = b[p++] + 7;
int s = c & 0x1F;
if (t != 1 && s >= 29) { int n = s - 28; s = 0; for (int i = 0; i < n; i++) s = (s << 8) | b[p++]; s += n == 1 ? 29 : n == 2 ? 285 : 65821; }
if (t == 1)
{
int ps = (c >> 3) & 3, pt = 0;
if (ps == 0) { pt = ((c & 0x07) << 8) | b[p++]; }
else if (ps == 1) { pt = ((c & 0x07) << 16) | (b[p++] << 8) | b[p++]; pt += 2048; }
else if (ps == 2) { pt = ((c & 0x07) << 24) | (b[p++] << 16) | (b[p++] << 8) | b[p++]; pt += 526336; }
else { pt = (b[p++] << 24) | (b[p++] << 16) | (b[p++] << 8) | b[p++]; }
int po = dss + pt;
return RVal(b, ref po, dss);
}
if (t == 2) { string r = System.Text.Encoding.UTF8.GetString(b, p, s); p += s; return r; }
if (t == 3) { byte[] db = new byte[8]; Array.Copy(b, p, db, 0, 8); if (BitConverter.IsLittleEndian) Array.Reverse(db); p += 8; return BitConverter.ToDouble(db, 0); }
if (t == 5 || t == 6 || t == 8 || t == 9 || t == 10) { long v = 0; for (int i = 0; i < s; i++) v = (v << 8) | b[p++]; return v; }
if (t == 7) return RMap(b, ref p, dss, s);
if (t == 11) { object[] a = new object[s]; for (int i = 0; i < s; i++) a[i] = RVal(b, ref p, dss); return a; }
if (t == 14) return s != 0;
p += s; return null;
}
private static Dictionary<string, object> RMap(byte[] b, ref int p, int dss, int sz = -1)
{
if (sz < 0) { int c = b[p++]; sz = c & 0x1F; if (sz >= 29) { int n = sz - 28; sz = 0; for (int i = 0; i < n; i++) sz = (sz << 8) | b[p++]; sz += n == 1 ? 29 : n == 2 ? 285 : 65821; } }
var m = new Dictionary<string, object>();
for (int i = 0; i < sz; i++) { string k = RVal(b, ref p, dss) as string; if (k != null) m[k] = RVal(b, ref p, dss); }
return m;
}
private static string GS(Dictionary<string, object> dict, string k1, string k2)
{
if (!dict.ContainsKey(k1)) return "";
var n = dict[k1] as Dictionary<string, object>;
return n != null && n.ContainsKey(k2) ? Convert.ToString(n[k2]) : "";
}
private static string GL(Dictionary<string, object> dict, string k1, string k2)
{
if (!dict.ContainsKey(k1)) return "";
var n = dict[k1] as Dictionary<string, object>;
if (n == null || !n.ContainsKey(k2)) return "";
var nm = n[k2] as Dictionary<string, object>;
return nm != null && nm.ContainsKey("en") ? Convert.ToString(nm["en"]) : "";
}
private static string GD(Dictionary<string, object> dict, string k1, string k2)
{
if (!dict.ContainsKey(k1)) return "";
var n = dict[k1] as Dictionary<string, object>;
if (n == null || !n.ContainsKey(k2)) return "";
object v = n[k2];
return v is double ? ((double)v).ToString(System.Globalization.CultureInfo.InvariantCulture) : Convert.ToString(v);
}
}
}
C#:
string json = Geo.GeoLite2.Lookup(project.Variables["IP"].Value);
if (json != null)
{
project.Variables["geo_json"].Value = json;
project.Json.FromString(json);
string country = project.Json.country_name;
string city = project.Json.city_name;
string timezone = project.Json.timezone;
string latitude = project.Json.latitude;
string longitude = project.Json.longitude;
string countryCode = project.Json.country_code;
// project.Variables["latitude"].Value = latitude;
}
C#:
string user_name = project.ExecuteMacro("{-Environment.UserName-}");
string json = Geo.GeoLite2.Lookup("8.8.8.8", $@"C:\Users\{user_name}\AppData\Roaming\ZennoLab\ZennoPoster\7\Data\GeoLite2-City.mmdb");
Надеюсь данное решение для вас будет полезным.
Ставьте спасибо и голос за работу
Последнее редактирование:

