Skocz do zawartości

Geolokalizacja adresu IP z bazy danych ip-api.com (API) [Filterscripts]


ELOSZKAPL
 Udostępnij

Rekomendowane odpowiedzi

W niniejszym temacie publikuję skrypt na pozyskiwanie geolokalizacji adresu IP z bazy danych serwisu ip-api.com, za pośrednictwem API.
 

Implementacje użytych funkcji:

Spoiler

stock ip2long(ip[])
{
  new res= 0x00000000, oct= 0;
  for(new idx= 0, val= 0, len= strlen(ip); oct < 4 && idx < len; oct++, idx++, val= 0)
  {
    for(new i= idx, j= 2; i < len-1; i++)
    {
      if (i-idx >= j) return 0x00000000;
      else if ('0' <= ip[i] <= '9') idx++;
      else if (ip[i] == '*') { j= 1; val= 0x00; break; }
      else if (ip[i] == '.') { idx= i; break; }
      else return 0x00000000;
    }
    if (ip[idx] == '.' && (idx == 0 || ip[--idx] == '.')) return 0x00000000;
    if (ip[idx] != '*') for(new i= idx, exp= 1; i >= 0 && ip[i] != '.'; i--)
    {
      if (!('0' <= ip[i] <= '9') || idx-i > 2) return 0x00000000;
      val += (ip[i]-'0')*exp; exp *= 10;
      if (val > 0xff) return 0x00000000;
    }
    res <<= 8; res += val; idx++;
  }

  if (oct < 4) return 0x00000000
  else return res << ((4-oct)*8);
}

 

Spoiler

stock strtok(dst[], src[], &idx, key= ' ', pos= 0, dst_sz= sizeof dst, src_ln= -1) // string to key
{
  if (pos >= dst_sz) return 0;

  new start= idx;
  for(new len= (src_ln < 0)?(strlen(src)):(src_ln); 0 <= idx < len; idx++)
  {
    if (!(0 <= idx-start < dst_sz)) return idx-start;
    if (src[idx] == 0x00 || src[idx] == 0x0D || src[idx] == 0x0A || src[idx] == key) break; // NULL, CR, LF, key
    dst[pos+idx-start]= src[idx];
  }

  dst[pos+idx-start]= 0; // EoS

  return pos+(idx++)-start;
}

 

Spoiler

stock json_getval(dest[], src[], field[], start= 0, dest_sz= sizeof dest)
{
  new slen= strlen(src);
  new flen= strlen(field);
  if (slen == 0 || flen == 0) return start;

  new idx= strfind(src, field, true, start);
  if (idx >= 0) idx += flen;
  else return start;

  dest[0]= 0;

  for(; idx < slen; idx++)
  {
    if (src[idx] == '"' || src[idx] == ':' || src[idx] == ' ') continue;
    else if (src[idx] == ',') return idx;
    else break;
  }

  new dlen= strtok(dest, src, idx, '"', 0, dest_sz, slen);
  if (dest[dlen-1] == ',') { dest[--dlen]= 0; idx--; }

  return dlen;
}

 

Spoiler

stock utf8_decode(str[], len= -1)
{
  if (len == 0) return 0;
  new slen= (len < 0)?(strlen(str)):(len);

  for(new i= 1; i < slen; i++)
  {
    switch(str[i-1])
    {
      case '0'..'9','A'..'Z','a'..'z': continue;

      case 0xC3: switch(str[i])
      {
        case 0x80..0xBF: str[i-1]= str[i]+0x40;
        default: continue;
      }
      case 0xC4: switch(str[i])
      {
        case 0x84: str[i-1]= 'Ą';
        case 0x85: str[i-1]= 'ą';
        case 0x86: str[i-1]= 'Ć';
        case 0x87: str[i-1]= 'ć';
        case 0x98: str[i-1]= 'Ę';
        case 0x99: str[i-1]= 'ę';
        default: continue;
      }
      case 0xC5: switch(str[i])
      {
        case 0x81: str[i-1]= 'Ł';
        case 0x82: str[i-1]= 'ł';
        case 0x83: str[i-1]= 'Ń';
        case 0x84: str[i-1]= 'ń';
        case 0x9A: str[i-1]= 'Ś';
        case 0x9B: str[i-1]= 'ś';
        case 0xB9: str[i-1]= 'Ź';
        case 0xBA: str[i-1]= 'ź';
        case 0xBB: str[i-1]= 'Ż';
        case 0xBC: str[i-1]= 'ż';
        default: continue;
      }

      default: continue;
    }

    strdel(str, i, i+1); slen--;
  }

  return slen;
}

Tylko dla polskich znaków!

Skrypt właściwy:

Spoiler

#include <a_samp>
#include <a_http>

// implementacje wyżej wymienionych funkcji
  
forward internal_OnGetPlayerGeoIp(playerid, http_code, data[]);
public internal_OnGetPlayerGeoIp(playerid, http_code, data[])
{
  if (http_code != 200) return;

  new ip[IP_MAXLEN+1]; json_getval(ip, data, "query");
  new timezone[32]; json_getval(timezone, data, "timezone");
  new country[32]; json_getval(country, data, "country"); utf8_decode(country);
  new city[32]; json_getval(city, data, "city"); utf8_decode(city);
  new isp[48]; json_getval(isp, data, "as"); utf8_decode(isp);
  new org[48]; json_getval(org, data, "org"); utf8_decode(org);

  CallRemoteFunction("OnGetPlayerGeoIp", "dssssss", playerid,ip,(timezone[0]!=0)?("null"):(timezone),(country[0]!=0)?("null"):(country),(city[0]!=0)?("null"):(city),(isp[0]!=0)?("null"):(isp),(org[0]!=0)?("null"):(org));
}

forward remote_GetPlayerGeoIp(playerid, ip[]);
public remote_GetPlayerGeoIp(playerid, ip[])
{
  if (!IsPlayerConnected(playerid)) return false;
  new ip2= ip2long(ip);
  if (ip2 == 0x00000000 || ip2 == 0x7f000001) return false; // 0.0.0.0, 127.0.0.1

  new url[32];
  format(url, sizeof(url), "ip-api.com/json/%s", ip);
  return HTTP(playerid, HTTP_GET, url, "", "internal_OnGetPlayerGeoIp");
}

public OnFilterScriptInit()
{
  // ...

  return 1;
}

public OnFilterScriptExit()
{
  // ...

  return 1;
}

 

Sposób użycia:

Spoiler

forward OnGetPlayerGeoIp(playerid, ip[], timezone[], country[], city[], isp[], org[]);
stock GetPlayerGeoIp(playerid, ip[]) return CallRemoteFunction("remote_GetPlayerGeoIp", "ds", playerid,ip);

public OnPlayerConnect(playerid)
{
  new ip[15+1]; GetPlayerIp(playerid, ip, sizeof(ip));
  GetPlayerGeoIp(playerid, ip);

  return 1;
}

public OnGetPlayerGeoIp(playerid, ip[], timezone[], country[], city[], isp[], org[])
{
  // wyświetlenie zwróconych informacji
}

 

Myślę, że choć jest trochę kodu to nie ma tu czego objaśniać, skoro sposób użycia jest dość prosty i skuteczny.


Proszę o wspomnienie mnie jako autora niniejszego skryptu

Odnośnik do komentarza
Udostępnij na innych stronach

Problem wciąż nierozwiązany? Dodaj swoją odpowiedź

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto. Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
 Udostępnij

×