Ansible Runner🟠 Позволяет интегрировать Ansible в Python-приложения🟠 Удобен для CI/CD, web-интерфейсов, API-сервисов🟠 Поддерживает запуск playbook, roles, adhoc-команд🟠 Управляет входными/выходными данными (stdout, artifacts)8
pip install ansible-runner
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍4
Скрипт, который сканирует список субдоменов, пытается определить уязвимые поддомены для takeover-а (например, Heroku, AWS S3, GitHub Pages и др.):
dns.resolver (из dnspython), requests, argparse, concurrent.futures🟠 Считывает субдомены из файла или принимает через CLI🟠 Разрешает CNAME- или A-записи DNS🟠 Если найден CNAME, сканирует по известным сигнатурам (“No such app”, “doesn’t exist”, “There isn’t a GitHub Pages site here” и др.) в HTTP-ответах🟠 Параллельно обрабатывает сотни запросов через ThreadPoolExecutor — что ускоряет проверку🟠 Помечает потенциально уязвимые хосты и сохраняет их в отчёт takeover_report.txt
python takeover_check.py --input subs.txt --dns-server 8.8.8.8 --timeout 5
#!/usr/bin/env python3
import argparse, re, requests
from dns import resolver, exception
from concurrent.futures import ThreadPoolExecutor
TAKEOVER_SIGNS = {
"heroku": re.compile(r'no such app', re.I),
"s3": re.compile(r'(NoSuchBucket|The specified bucket does not exist)', re.I),
"github": re.compile(r"There isn't a GitHub Pages site here", re.I),
"azure": re.compile(r'No DNS record found for', re.I),
}
def find_cname(host, nameserver, timeout):
res = resolver.Resolver()
res.nameservers = [nameserver]
res.timeout = timeout
res.lifetime = timeout
try:
answers = res.resolve(host, 'CNAME')
return str(answers[0].target).rstrip('.')
except (resolver.NoAnswer, resolver.NXDOMAIN):
return None
except exception.DNSException:
return None
def check_takeover(host, cname, timeout):
if not cname:
return None
url = f"http://{host}"
try:
r = requests.get(url, timeout=timeout)
html = r.text
for provider, pattern in TAKEOVER_SIGNS.items():
if pattern.search(html):
return (provider, r.status_code, len(html))
except requests.RequestException:
pass
return None
def process(host, nameserver, timeout):
cname = find_cname(host, nameserver, timeout)
suspect = check_takeover(host, cname, timeout)
return host, cname, suspect
def main(args):
heads = f"# Subdomain Takeover Scan Report: {args.input}"
print(heads)
with open(args.input) as f:
hosts = [h.strip() for h in f if h.strip()]
report = []
with ThreadPoolExecutor(max_workers=args.threads) as pool:
for host, cname, res in pool.map(lambda h: process(h, args.nameserver, args.timeout), hosts):
if res:
provider, code, size = res
msg = f"⚠️ {host} → potential {provider} takeover (cname: {cname}, code: {code}, size: {size})"
print(msg)
report.append(msg)
if report:
with open("takeover_report.txt", "w") as f:
f.write(heads + "\n\n" + "\n".join(report))
print(f"\n✅ Найдено потенциальных уязвимостей: {len(report)}. Сохранил в takeover_report.txt")
else:
print("\n✅ Уязвимых поддоменов не найдено.")
if __name__ == "__main__":
cli = argparse.ArgumentParser(description="Subdomain Takeover Checker")
cli.add_argument("--input", "-i", required=True, help="Файл со списком субдоменов, один домен на строку")
cli.add_argument("--dns-server", default="8.8.8.8", help="DNS сервер для запросов (по умолчанию: Google)")
cli.add_argument("--timeout", type=float, default=4.0, help="Таймаут DNS и HTTP")
cli.add_argument("--threads", type=int, default=50, help="Параллельность (подъем числа при больших wordlists)")
args = cli.parse_args()
main(args)
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
2❤5🔥2
Compare‑Dicts‑Lib (compare_dicts_lib)🟠 Поддержка вложенных структур, списков и match-патчинг по "id"🟠 Простое сравнение: compare_dicts(new, old) возвращает только изменения🟠 Флаг detailed=True — показывает тип изменений, старое и новое значение🟠 Параметры: ignore_keys=[…], strict_type_checking=False🟠 Можно применять diff через apply_diff(...) прямо к данным🟠 Не требует сторонних зависимостей, лицензия MIT, Python 3.7+ поддерживается
pip install compare-dicts-lib
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥4
GitPython, openai, sys, os, argparse, logging🟠 Берёт git diff --cached (или нестейдженные изменения) с помощью GitPython или repo.git в чистом виде🟠 Формирует запрос (prompt) к OpenAI: «You are an expert developer. Here is a git diff, write a concise, meaningful commit message.»🟠 Предлагает выбрать или отредактировать сгенерированный вариант🟠 При подтверждении выполняет git commit -m "..." либо передаёт через stdin git commit🟠 Работает как CLI: можно передавать флаги --no-gpt (fallback), --amend, --language=ru и т.п.🟠 Подходит для любого Git‑проекта, схема LLM‑ный генератор месседжей описана на LevelUp и Python in Plain English
# с абсолютной осторожностью: ничего не коммитите вручную — AI предложит сообщение
python ai_commit.py
import os, argparse, logging
from git import Repo
import openai
import sys
openai.api_key = os.getenv("OPENAI_API_KEY")
def get_diff(repo_path='.', staged=True):
repo = Repo(repo_path)
if staged:
return repo.git.diff('--cached', unified=3)
else:
return repo.git.diff(unified=3)
def ask_ai(diff_text, lang='en'):
prompt = (
f"You are an expert software developer.\n"
f"Provide a concise single-line commit message in {lang} for the following git diff:\n\n{diff_text}"
)
resp = openai.ChatCompletion.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0.2, max_tokens=60
)
return resp.choices[0].message.content.strip()
def main():
cli = argparse.ArgumentParser(description="AI Commit Message Generator")
cli.add_argument('--no-gpt', action='store_true', help="Use default message prompt 'Update changes'")
cli.add_argument('--stage-all', action='store_true', help="Add all changes")
cli.add_argument('--language', default='en', help="Commit message language (e.g. 'ru', 'en')")
args = cli.parse_args()
repo = Repo('.')
if args.stage_all:
repo.git.add('--all')
diff = get_diff(staged=True)
if not diff.strip():
print("Нет изменений для коммита.")
sys.exit(1)
msg = "Update changes (no GPT mode)" if args.no_gpt else ask_ai(diff, lang=args.language)
print(f"\n> Suggested commit message:\n{msg}\n")
choice = input("[c]ommit / [e]dit / [s]kip? ").lower()
if choice.startswith('c'):
repo.git.commit('-m', msg)
print("✅ Committed.")
elif choice.startswith('e'):
ed = input("Input your commit message: ").strip()
if ed:
repo.git.commit('-m', ed)
print("✅ Committed with custom message.")
else:
print("✳️ Empty message. Aborting.")
else:
print("⚠️ Commit skipped.")
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
main()
pip install GitPython openai python-dotenv
(Рекомендуется: настроить OPENAI_API_KEY через .env или переменную окружения).
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍4🔥2
PhotoHolmes🟠 Готовые продвинутые методы: Adaptive CFA‑Net, CAT‑Net, FOCAL и др., на основе шумовой аномалии и локальных паттернов🟠 Модули для популярных датасетов (Columbia, CASIA, DSO‑1) — загрузка, предобработка, использование в оценке🟠 Benchmark API — сравните метод на датасете по метрикам F1‑score, IoU, MCC и др., с результатами в JSON/CSV🟠 Командный интерфейс (CLI): оценка конкретной картинки или запуск бенчмарка на папке в 1 команду🟠 Открытая, модульная архитектура: легко добавить свою логику, метрику или набор изображений для тестирования🟠 Лицензия Apache‑2.0; Python >= 3.10; активно развивается и имеет GitHub сообщество.
pip install git+https://github.com/photoholmes/photoholmes.git
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4❤2🥰1
requests, ctypes (Windows) или os + gsettings (Linux), argparse, schedule, platform, time🟠 Загружает фоновое изображение дня от Bing (или другого источника)🟠 Сохраняет картинку локально🟠 Устанавливает её как обои на рабочем столе🟠 Можно запускать ежедневно через cron или использовать встроенный scheduler Python
python auto_wallpaper.py --dir ~/Pictures/BingWall --daily --source bing
👨💻 Код скрипта:
import os, requests, platform, argparse, schedule, time
from datetime import datetime
def fetch_bing_wallpaper(save_dir):
data = requests.get('https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1').json()
url = 'https://www.bing.com' + data['images'][0]['url']
fname = os.path.join(save_dir, datetime.now().strftime('bing_%Y%m%d.jpg'))
resp = requests.get(url)
with open(fname, 'wb') as f: f.write(resp.content)
return fname
def set_wallpaper(path):
sys = platform.system()
if sys == 'Windows':
import ctypes
ctypes.windll.user32.SystemParametersInfoW(20, 0, path, 3)
elif sys == 'Linux':
os.system(f"gsettings set org.gnome.desktop.background picture-uri file://{path}")
# MacOS: можно через osascript — добавьте при необходимости
def job(args):
img = fetch_bing_wallpaper(args.dir)
set_wallpaper(img)
print(f"✅ Wallpaper updated: {img}")
def main():
p = argparse.ArgumentParser(description="Auto Wallpaper Changer")
p.add_argument('--dir', default=os.getcwd(), help="Папка для сохранения обоев")
p.add_argument('--daily', action='store_true', help="Менять обои каждый день")
args = p.parse_args()
os.makedirs(args.dir, exist_ok=True)
if args.daily:
schedule.every().day.at("07:00").do(job, args)
print("🚀 Wallpaper scheduler started")
while True:
schedule.run_pending()
time.sleep(60)
else:
job(args)
if __name__ == "__main__":
main()
pip install requests schedule
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤8🔥4
jenkinsapi 🟠 Получение статуса сборок🟠 Запуск/остановка job'ов🟠 Управление параметрами сборок🟠 Работа с логами, артефактами и queue🟠 Интеграция Jenkins в Python-скрипты
pip install jenkinsapi
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🔥2
intelx 🟠 Поиск в утечках (email, пароли, домены, IP и др.)🟠 Доступ к API IntelligenceX🟠 Получение и скачивание найденных записей
pip install intelx-sdk
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥4👍3
pydub, argparse, os, scipy.signal (только если нужен алгоритм кластеризации пауз)🟠 Загружает аудиофайл (.mp3, .wav и др.)🟠 Находит паузы длиннее заданного порога (например, тишина ≥ 2 секунды)🟠 Делит трек на сегменты между этими паузами🟠 Сохраняет каждый сегмент как отдельный файл с порядковым номером🟠 Подходит для подкастов, интервью, лекций — автоматизирует разделение аудио
python split_audio.py --input lecture.mp3 --silence_thresh -40 --min_silence_len 2000 --output segmented/
import os
import argparse
from pydub import AudioSegment
from pydub.silence import detect_silence
def split_on_silence(input_path, silence_thresh=-40, min_silence_len=2000, keep_silence=500, output_dir="segments"):
audio = AudioSegment.from_file(input_path)
os.makedirs(output_dir, exist_ok=True)
silence_ranges = detect_silence(audio, min_silence_len=min_silence_len, silence_thresh=silence_thresh)
silence_ranges = [(start, stop) for start, stop in silence_ranges]
prev_end = 0
count = 1
for start, stop in silence_ranges:
segment = audio[prev_end:start]
segment_name = os.path.join(output_dir, f"segment_{count:03}.mp3")
segment.export(segment_name, format="mp3")
print(f"✅ Saved {segment_name}")
count += 1
prev_end = stop
# last segment
if prev_end < len(audio):
segment = audio[prev_end:]
segment_name = os.path.join(output_dir, f"segment_{count:03}.mp3")
segment.export(segment_name, format="mp3")
print(f"✅ Saved {segment_name}")
def main():
parser = argparse.ArgumentParser(description="Split audio on silence into chapters")
parser.add_argument("--input", required=True, help="Input audio file (mp3/wav/etc.)")
parser.add_argument("--silence_thresh", type=int, default=-40, help="Threshold (dBFS) to detect silence")
parser.add_argument("--min_silence_len", type=int, default=2000, help="Minimum silence length (ms)")
parser.add_argument("--keep_silence", type=int, default=500, help="Silence to leave at edges (ms)")
parser.add_argument("--output", default="segments", help="Directory to save segments")
args = parser.parse_args()
split_on_silence(args.input, args.silence_thresh, args.min_silence_len, args.keep_silence, args.output)
if __name__ == "__main__":
main()
pip install pydub
Также потребуется ffmpeg или avlib — убедись, что установлен!
🟠 Разбивка подкастов, лекций или интервью на главы🟠 Подготовка аудио к конвертации, генерации транскрипта по части🟠 Автоматизация медиа-обработки для подкастеров и создателей контента
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍3🔥3
APSW🟠 Почти 1:1 маппинг на C API SQLite🟠 Позволяет использовать расширенные функции SQLite, включая виртуальные таблицы, бэкапы, трассировки и т.п.🟠 Подходит для продвинутого контроля транзакций и производительности
pip install apsw
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥3👍2
invoke 🟠 Задачи оформляются как обычные Python-функции🟠 Можно группировать задачи в namespaces🟠 Лёгкая интеграция с CI/CD
pip install invoke
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
3❤4👍3🔥1
psutil, smtplib, subprocess, argparse, time🟠 Мониторит ресурсы (CPU, RAM, диск)🟠 При превышении порога — запускает "лечащие" действия, например: systemctl restart your_service или rm -rf /tmp/*🟠 Отправляет предупреждение по email — сразу знаешь, что было не так🟠 Позволяет автоматизировать восстановление без вмешательства человека
python self_healing_monitor.py \
--cpu-threshold 85 \
--disk-threshold 90 \
--memory-threshold 80 \
--heal-cmd "systemctl restart nginx" \
--email you@example.com
import psutil, smtplib, time, argparse, subprocess
from email.message import EmailMessage
def send_alert(email, subject, content):
msg = EmailMessage()
msg.set_content(content)
msg["Subject"] = subject
msg["From"] = email
msg["To"] = email
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as smtp:
smtp.login(email, "YOUR_APP_PASSWORD")
smtp.send_message(msg)
def monitor(cpu_th, mem_th, disk_th, heal_cmd, email, interval):
while True:
cpu = psutil.cpu_percent(interval=1)
mem = psutil.virtual_memory().percent
disk = psutil.disk_usage('/').percent
if cpu > cpu_th or mem > mem_th or disk > disk_th:
subject = "⚠️ System Alert"
body = f"CPU: {cpu}%, MEM: {mem}%, DISK: {disk}%\nRunning heal command..."
print(body)
if heal_cmd:
subprocess.run(heal_cmd, shell=True)
if email:
send_alert(email, subject, body)
time.sleep(interval)
if __name__ == "__main__":
p = argparse.ArgumentParser("Self-Healing System Monitor")
p.add_argument("--cpu-threshold", type=int, default=80)
p.add_argument("--memory-threshold", type=int, default=80)
p.add_argument("--disk-threshold", type=int, default=80)
p.add_argument("--heal-cmd", default=None, help="Command to run when threshold reached")
p.add_argument("--email", default=None, help="Email to send alerts to")
p.add_argument("--interval", type=int, default=60, help="Check interval in seconds")
args = p.parse_args()
monitor(args.cpu_threshold, args.memory_threshold, args.disk_threshold, args.heal_cmd, args.email, args.interval)
pip install psutil
Также должен быть настроен SMTP (например, GMail с app password) — для email-уведомлений.
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍4❤3🔥3
yaspin🟠 Не требует внешних зависимостей, работает на всех версиях CPython и PyPy🟠 Поддерживает свыше 70 видов спиннеров из cli-spinners и цветовые оформления через termcolor🟠 Интуитивный API: можно использовать как контекстный менеджер, декоратор функции или вручную управлять состояниями (start, stop, succeed, fail)🟠 Устойчив к перенаправлению вывода — корректно работает при выводе в .log или через grep
pip install yaspin
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤5🔥3👍2
requests, random, itertools, (опционально) fake_useragent, proxy list🟠 С рандомным User-Agent из списка для каждого HTTP-запроса🟠 Использует список прокси, отдавая по одному на каждый запрос🟠 Повышает анонимность: меняется IP + заголовки🟠 Полезен для OSINT, скрейпинга, разведки и обхода банов
python rotator.py urls.txt user_agents.txt proxies.txt
import requests, random
from itertools import cycle
import argparse
def load_list(path):
with open(path, encoding='utf-8') as f:
return [l.strip() for l in f if l.strip()]
def main(urls_file, ua_file, proxy_file, delay=1):
urls = load_list(urls_file)
uas = cycle(load_list(ua_file))
proxies = cycle(load_list(proxy_file))
for url in urls:
ua = next(uas)
proxy = next(proxies)
headers = {'User-Agent': ua}
proxy_dict = {'http': proxy, 'https': proxy}
try:
resp = requests.get(url, headers=headers, proxies=proxy_dict, timeout=10)
print(f"[{resp.status_code}] {url} — UA: {ua[:30]}... via {proxy}")
except Exception as e:
print(f"❌ {url} — fail: {e}")
time.sleep(delay)
if __name__ == '__main__':
p = argparse.ArgumentParser("UA + Proxy Rotator")
p.add_argument("urls", help="File with URLs list")
p.add_argument("uas", help="File with User-Agent strings")
p.add_argument("proxies", help="File with proxies (host:port)")
p.add_argument("--delay", type=int, default=1, help="Delay between requests (s)")
args = p.parse_args()
main(args.urls, args.uas, args.proxies, args.delay)
pip install requests
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤6👍4🔥3
NApy🟢 Оптимизированные статистические тесты с параллелизацией на уровне C++/OpenMP для больших наборов данных🟢 Автоматическая обработка гетерогенных столбцов и пропущенных значений🟢 Работа в интерактивных приложениях и потоках — моментальные результаты без задержек🟢 Превосходит по скорости и потреблению памяти аналоги на чистом Python
pip install napy
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍2🔥2
Плюс можно регулировать скорость воспроизведения — удобный способ добавить ретро-эффект или наблюдать видео, даже если нет GUI.
ascii-magic, PIL, opencv-python🟠 Извлекает кадры из видео с помощью OpenCV (cv2)🟠 Преобразует каждый кадр в ASCII-арт через ascii-magic и Pillow🟠 Выводит видео как последовательность ASCII-картинок в терминал🟠 Можно менять скорость воспроизведения🟠 Совместим с Windows (там работает стабильно)
python main.py path_to_video.mp4
# Впиши + или - для управления скоростью, q — выйти
from ascii_magic import from_image
from PIL import Image
import cv2
import sys
import time
def play_ascii_video(path, fps=10):
cap = cv2.VideoCapture(path)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
ascii_frame = from_image(image, columns=80, char="#")
print("\033c", end="") # очистка терминала
print(ascii_frame)
time.sleep(1 / fps)
cap.release()
(это упрощённый пример, библиотека ascii-magic обеспечивает основное преобразование и управляет выводом на экран)
pip install ascii-magic pillow opencv-python
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤6👍3🔥2
pyWATTS🟠 Поддержка непоследовательных (не-sequential) пайплайнов: можно комбинировать модули и выстраивать сложные цепочки обработки данных🟠 Чёткие интерфейсы и возможность повторного использования шагов ("subpipelining"), что упрощает повторимость экспериментов и качественное структурирование задач🟠 Возможность загрузки/сохранения пайплайнов, что облегчает воспроизводимость результатов🟠 Интеграция с популярными ML-фреймворками: scikit-learn, PyTorch, Keras, без лишних конвертаций и костылей
pip install pywatts
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤4👍2🔥2
🟠 Работает через Python, минимум зависимостей (python-dateutil + стандартная библиотека)🟠 Показывает маршрут письма (hop chain), включая IP, Host, время задержки🟠 CLI-интерфейс: передаёшь файл — получаешь аналитику в терминале🟠 Лёгкий, быстрый, без GUI, прямо как для тебя надо
./tracemail.py -r email_sample.eml
# — покажет список hop’ов: от кого до кого, IP, delay в секундах
#!/usr/bin/env python3
import sys
from email import message_from_file
from datetime import datetime
from dateutil import parser as dateparser
def parse_hops(email_path):
msg = message_from_file(open(email_path, encoding='utf-8'))
received = msg.get_all('Received') or []
hops = []
for header in received:
parts = header.split(';')
from_part = parts[0].strip()
date_part = parts[-1].strip()
try:
ts = dateparser.parse(date_part)
except:
ts = None
hops.append((from_part, ts))
return hops
def print_hops(hops):
for i in range(len(hops)-1):
src, t1 = hops[i]
_, t2 = hops[i+1]
delay = (t1 - t2).total_seconds() if t1 and t2 else '?'
print(f"Hop {i+1}: {src} — Delay: {delay}s")
if hops:
print(f" final hop: {hops[-1][0]}")
if __name__ == '__main__':
if len(sys.argv) < 3 or sys.argv[1] != '-r':
print("Usage: tracemail.py -r <email_file>")
sys.exit(1)
hops = parse_hops(sys.argv[2])
print_hops(hops)
pip install python-dateutil
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍5🔥4❤3
CyNER🟠 Поддерживает выделение как общих (имена, организации), так и специализированных cyber-сущностей, включая IoC.🟠 Комбинирует трансформерные модели с эвристическими правилами — точнее, чем простые NER-библиотеки.🟠 Подходит для автоматизированного анализа отчетов, логов и текстов разведки.
pip install cyner
#библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤6👍4🔥2
phonenumbers, folium, opencage (при наличии API-ключа), argparse, colorama🟠 Парсит номер, определяет страну, тип номера (мобила/стационар), часовой пояс и оператора — через phonenumbers🟠 При наличии ключа OpenCage — преобразует локацию в координаты и строит интерактивную карту через folium, сохраняет как HTML🟠 Выделяет важные части цветом через colorama, чтобы сразу видеть страну, оператора и локацию — сок в UX
python phone_info.py --number "+1234567890" --map --key YOUR_OPENCAGE_API_KEY
import argparse
import phonenumbers
from phonenumbers import geocoder, carrier, timezone
import folium
from opencage.geocoder import OpenCageGeocode
from colorama import init, Fore
init()
def get_info(number):
pn = phonenumbers.parse(number)
info = {
"formatted": phonenumbers.format_number(pn, phonenumbers.PhoneNumberFormat.INTERNATIONAL),
"country": geocoder.description_for_number(pn, "en"),
"carrier": carrier.name_for_number(pn, "en"),
"timezone": timezone.time_zones_for_number(pn)
}
return info
def create_map(location_name, api_key, output="map.html"):
geocoder = OpenCageGeocode(api_key)
results = geocoder.geocode(location_name)
if results:
lat, lng = results[0]['geometry']['lat'], results[0]['geometry']['lng']
m = folium.Map(location=[lat, lng], zoom_start=7)
folium.Marker([lat, lng], popup=location_name).add_to(m)
m.save(output)
return output
return None
if __name__ == "__main__":
p = argparse.ArgumentParser("Phone Info with Map")
p.add_argument("--number", required=True, help="Phone number with country code")
p.add_argument("--map", action="store_true", help="Generate map HTML")
p.add_argument("--key", help="OpenCage API key for map")
args = p.parse_args()
info = get_info(args.number)
print(f"{Fore.GREEN}Number: {info['formatted']}")
print(f"{Fore.CYAN}Country: {info['country']}")
print(f"{Fore.YELLOW}Carrier: {info['carrier']}")
print(f"{Fore.MAGENTA}Timezone: {', '.join(info['timezone'])}")
if args.map and args.key:
path = create_map(info['country'], args.key)
if path:
print(f"{Fore.BLUE} Map saved to: {path}")
else:
print(f"{Fore.RED}Failed to generate map")
pip install phonenumbers folium opencage colorama
Обязательно нужен ключ от OpenCage для геокодинга. Базовая инфа — по коду и структуре — без карты — тоже работает.
#скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
2❤9👍7🔥3