Первый выпуск

This commit is contained in:
Sergey Kalinin
2025-12-04 11:30:32 +03:00
commit bacc0de2fd
8 changed files with 1439 additions and 0 deletions

502
templates/index.html Normal file
View File

@@ -0,0 +1,502 @@
<!DOCTYPE html>
<html>
<head>
<title>Поиск по GeoIP и Whois</title>
<meta charset="utf-8">
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1600px;
margin: 0 auto;
background: white;
padding: 10px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 10px;
}
h1 {
color: #333;
margin: 0;
font-size: 24px;
}
.content {
padding: 0;
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 15px;
max-width: 600px;
}
input[type="text"] {
flex: 1;
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 14px;
transition: border-color 0.3s;
}
input[type="text"]:focus {
outline: none;
border-color: #007bff;
}
button {
padding: 8px 16px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: normal;
transition: background 0.3s;
}
button:hover {
background: #0056b3;
}
.result {
margin-top: 15px;
padding: 15px;
background: #f8f9fa;
border-radius: 6px;
border-left: 3px solid #007bff;
}
.result h3 {
color: #333;
margin-bottom: 12px;
font-size: 18px;
}
.json-view {
background: #2c3e50;
color: #ecf0f1;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
font-family: 'Courier New', monospace;
font-size: 13px;
line-height: 1.4;
white-space: pre-wrap;
}
.error {
background: #dc3545;
color: white;
padding: 12px;
border-radius: 4px;
margin-top: 15px;
font-size: 14px;
}
.success {
background: #28a745;
color: white;
padding: 8px 12px;
border-radius: 4px;
margin-bottom: 12px;
display: inline-block;
font-size: 14px;
}
.locale-info {
background: #ffc107;
color: #856404;
padding: 6px 10px;
border-radius: 4px;
margin-bottom: 12px;
display: inline-block;
font-size: 13px;
}
.examples {
margin-top: 20px;
padding: 15px;
background: #e9ecef;
border-radius: 6px;
}
.examples h3 {
margin-bottom: 12px;
color: #495057;
font-size: 16px;
}
.example-ips {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.example-ip {
padding: 6px 12px;
background: #007bff;
color: white;
border-radius: 3px;
cursor: pointer;
font-size: 13px;
transition: background 0.3s;
text-decoration: none;
border: 1px solid #007bff;
}
.example-ip:hover {
background: #0056b3;
text-decoration: none;
color: white;
}
.footer {
text-align: center;
padding: 12px 0;
color: #777;
font-size: 0.85em;
border-top: 1px solid #eee;
background: white;
margin-top: 20px;
border-radius: 8px;
}
.data-section {
margin: 15px 0;
background: white;
padding: 12px;
border-radius: 4px;
border: 1px solid #dee2e6;
}
.data-section h4 {
color: #007bff;
margin-bottom: 1px;
border-bottom: 1px solid #dee2e6;
padding-bottom: 4px;
font-size: 16px;
}
.data-section hr {
border-bottom: 1px solid #dee2e6;
border-color: #dee2e6;
background-color: #dee2e6;
color: #dee2e6;
}
.data-item {
margin: 4px 0;
display: flex;
padding: 3px 0;
}
.data-label {
font-weight: bold;
min-width: 150px;
color: #333;
font-size: 14px;
}
.data-value {
color: #495057;
font-size: 14px;
}
.locale-selector {
margin: 12px 0;
padding: 8px;
background: #f8f9fa;
border-radius: 4px;
border: 1px solid #e9ecef;
}
.locale-selector label {
font-weight: bold;
margin-right: 8px;
font-size: 14px;
color: #495057;
}
select {
padding: 6px 10px;
border: 1px solid #ced4da;
border-radius: 3px;
background: white;
font-size: 14px;
}
.no-data {
color: #6c757d;
font-style: italic;
}
.filters {
background: #f8f9fa;
padding: 8px;
border-radius: 6px;
margin-bottom: 15px;
border: 1px solid #e9ecef;
}
.filters h3 {
margin: 0 0 8px 0;
color: #495057;
font-size: 16px;
}
.search-form {
display: flex;
gap: 4px;
margin: 4px 0;
}
.search-input {
flex: 1;
padding: 5px 8px;
border: 1px solid #ced4da;
border-radius: 3px;
font-size: 13px;
}
.search-button {
padding: 5px 10px;
background: #28a745;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 13px;
}
.search-button:hover {
background: #218838;
}
.ip-container {
display: flex;
align-items: center;
gap: 6px;
}
.whois-link {
display: inline-block;
padding: 1px 4px;
background: #17a2b8;
color: white;
text-decoration: none;
border-radius: 2px;
font-size: 9px;
font-weight: normal;
}
.whois-link:hover {
background: #138496;
text-decoration: none;
}
.alarm-action-true {
color: #28a745;
font-weight: bold;
}
.alarm-action-false {
color: #dc3545;
font-weight: bold;
}
@media (max-width: 768px) {
.header-container {
flex-direction: column;
align-items: flex-start;
}
.input-group {
flex-direction: column;
}
.data-item {
flex-direction: column;
}
.data-label {
min-width: auto;
margin-bottom: 2px;
}
}
footer {
text-align: center;
padding: 12px 0;
color: #777;
font-size: 0.85em;
border-top: 1px solid #eee;
background: white;
margin-top: auto;
position: sticky;
bottom: 0;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.footer-links, .header-links {
margin-top: 6px;
text-decoration: none;
}
.header-links {
text-decoration: none;
}
.current-url {
background: #e9ecef;
padding: 8px 12px;
border-radius: 4px;
margin: 10px 0;
font-family: 'Courier New', monospace;
font-size: 12px;
word-break: break-all;
border: 1px solid #dee2e6;
}
</style>
</head>
<body>
<div class="container">
<div class="header-container">
<a href={{.BaseURL}} class="header-links"><h1>🌍 Поиск по GeoIP и Whois</h1></a>
<div class="locale-selector">
<label for="locale">Язык:</label>
<select id="locale">
<option value="auto">Авто</option>
<option value="en">Английский</option>
<option value="de">Немецкий</option>
<option value="es">Испанский</option>
<option value="fr">Французский</option>
<option value="ja">Японский</option>
<option value="pt-BR">Португальский (Бразилия)</option>
<option value="ru">Русский</option>
<option value="zh-CN">Китайский</option>
</select>
</div>
</div>
<div class="content">
<div class="filters">
<h3>Введите IP адрес</h3>
<form method="GET" action="/">
<div class="input-group">
<input type="text" name="ip" placeholder="Введите IP адрес (например, 8.8.8.8)"
value="{{if .GeoData}}{{.GeoData.IPAddress}}{{end}}">
<button type="submit">Найти</button>
</div>
</form>
<!--
<button onclick="lookupMyIp()" style="background: #28a745;">Lookup My IP</button>
-->
</div>
<div id="result">
{{if .Error}}
<div class="error">
<strong>Error:</strong> {{.Error}}
</div>
{{end}}
{{if .GeoData}}
<!--
<div class="result">
<div class="success">✓ Data retrieved successfully</div>
{{if .Metadata.LocaleUsed}}
<div class="locale-info">🌐 Display language: {{.Metadata.LocaleUsed}}</div>
{{end}}
-->
<h3>Результат поиска для {{.IPAddress}}</h3>
<div class="data-section">
<b>🌐 Местоположение:</b>
<br><br>
<div class="data-item">
<div class="data-label">Страна:</div>
<div class="data-value">{{if .Location.Country}}{{.Location.Country}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Регион:</div>
<div class="data-value">{{if .Location.Region}}{{.Location.Region}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Код региона :</div>
<div class="data-value">{{if .Location.RegionISO}}{{.Location.RegionISO}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Город:</div>
<div class="data-value">{{if .Location.City}}{{.Location.City}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Континент:</div>
<div class="data-value">{{if .Location.Continent}}{{.Location.Continent}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Координаты:</div>
<div class="data-value">
{{if .Location.Latitude}}{{.Location.Latitude}}, {{.Location.Longitude}}{{else}}<span class="no-data">N/A</span>{{end}}
</div>
</div>
<div class="data-item">
<div class="data-label">Временная зона:</div>
<div class="data-value">{{if .Location.TimeZone}}{{.Location.TimeZone}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Почтовый индекс:</div>
<div class="data-value">{{if .Location.PostalCode}}{{.Location.PostalCode}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
</div>
<div class="data-section">
<b>🌐 Информация о операторе:</b>
<br><br>
<div class="data-item">
<div class="data-label">ASN:</div>
<div class="data-value">{{if .Network.ASN}}{{.Network.ASN}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Организация:</div>
<div class="data-value">{{if .Network.ASOrg}}{{.Network.ASOrg}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
</div>
<div class="data-section">
<b>📋 Международный код (ISO):</b>
<br><br>
<div class="data-item">
<div class="data-label">Код страны:</div>
<div class="data-value">{{if .Codes.CountryISO}}{{.Codes.CountryISO}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
<div class="data-item">
<div class="data-label">Код континента:</div>
<div class="data-value">{{if .Codes.ContinentISO}}{{.Codes.ContinentISO}}{{else}}<span class="no-data">N/A</span>{{end}}</div>
</div>
</div>
<div class="data-section">
<b>🔒 Дополнительная информация:</b>
<br><br>
<div class="data-item">
<div class="data-label">Анонимный прокси:</div>
<div class="data-value {{if .Security.IsAnonymousProxy}}alarm-action-true{{else}}alarm-action-false{{end}}">
{{if .Security.IsAnonymousProxy}}Yes{{else}}No{{end}}
</div>
</div>
<div class="data-item">
<div class="data-label">Спутниковый провайдер:</div>
<div class="data-value {{if .Security.IsSatelliteProvider}}alarm-action-true{{else}}alarm-action-false{{end}}">
{{if .Security.IsSatelliteProvider}}Yes{{else}}No{{end}}
</div>
</div>
</div>
<!--
{{if .JSONData}}
<div class="data-section">
<b>📄 Полученные данные (JSON)</b>
<div class="json-view">{{.JSONData}}</div>
</div>
{{end}}
-->
{{if .WhoIsData}}
<div class="data-section">
<b>🌐 Данные Whois:</b>
<br><br>
<div class="json-view">{{.WhoIsData}}</div>
</div>
{{end}}
</div>
{{end}}
</div>
<div class="examples">
<h3>Дополнительные команды:</h3>
<p>Данный сервис можно использовать для получения данных в JSON:
<div class="current-url">
<span id="current-url-display">{{.BaseURL}}/api/x.x.x.x</span>
</div>
<p>Для получения информации ввиде html:
<div class="current-url">
<span id="current-url-display">{{.BaseURL}}/x.x.x.x</span>
</div>
</div>
</div>
</div>
<p>
<footer>
<div>© <script>document.write(new Date().getFullYear())</script> СВК</div>
<div>Данные предоставлены MaxMind. Последнее обновление - {{.DBVersion}}</div>
</footer>
</body>
</html>