yougotmapped 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yougotmapped-1.0.0/LICENSE +27 -0
- yougotmapped-1.0.0/MANIFEST.in +2 -0
- yougotmapped-1.0.0/PKG-INFO +133 -0
- yougotmapped-1.0.0/README.md +103 -0
- yougotmapped-1.0.0/setup.cfg +4 -0
- yougotmapped-1.0.0/setup.py +32 -0
- yougotmapped-1.0.0/yougotmapped/__init__.py +0 -0
- yougotmapped-1.0.0/yougotmapped/cli.py +175 -0
- yougotmapped-1.0.0/yougotmapped/utils/__init__.py +0 -0
- yougotmapped-1.0.0/yougotmapped/utils/anonymity.py +53 -0
- yougotmapped-1.0.0/yougotmapped/utils/dependencies.py +33 -0
- yougotmapped-1.0.0/yougotmapped/utils/mapping.py +66 -0
- yougotmapped-1.0.0/yougotmapped/utils/network.py +34 -0
- yougotmapped-1.0.0/yougotmapped/utils/output.py +67 -0
- yougotmapped-1.0.0/yougotmapped/utils/ping.py +56 -0
- yougotmapped-1.0.0/yougotmapped/utils/token.py +31 -0
- yougotmapped-1.0.0/yougotmapped/utils/trace.py +70 -0
- yougotmapped-1.0.0/yougotmapped.egg-info/PKG-INFO +133 -0
- yougotmapped-1.0.0/yougotmapped.egg-info/SOURCES.txt +21 -0
- yougotmapped-1.0.0/yougotmapped.egg-info/dependency_links.txt +1 -0
- yougotmapped-1.0.0/yougotmapped.egg-info/entry_points.txt +2 -0
- yougotmapped-1.0.0/yougotmapped.egg-info/requires.txt +4 -0
- yougotmapped-1.0.0/yougotmapped.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 diputs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the “Software”), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
📝 Side note from the author:
|
|
26
|
+
If this script crashes your terminal or geo-locates your toaster... that's on you.
|
|
27
|
+
But hey — it worked flawlessly on my end. 🫠
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yougotmapped
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A terminal tool to map IPs and domains with style.
|
|
5
|
+
Home-page: https://github.com/diputs-sudo/YouGotMapped
|
|
6
|
+
Author: diputs
|
|
7
|
+
Author-email: diputs-sudo@proton.me
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.7
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests
|
|
16
|
+
Requires-Dist: folium
|
|
17
|
+
Requires-Dist: python-dotenv
|
|
18
|
+
Requires-Dist: ping3
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: author-email
|
|
21
|
+
Dynamic: classifier
|
|
22
|
+
Dynamic: description
|
|
23
|
+
Dynamic: description-content-type
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
30
|
+
|
|
31
|
+
# 🌍 YouGotMapped — IP Geolocation Mapper
|
|
32
|
+
|
|
33
|
+
Ever wondered where that weird IP pinging your router is *actually* from?
|
|
34
|
+
Or maybe you're just nosy (respect). Either way — this script's for you.
|
|
35
|
+
|
|
36
|
+
**YouGotMapped** is a sassy little Python tool that:
|
|
37
|
+
- Auto-fetches your IP (if you dare expose yourself)
|
|
38
|
+
- Accepts any domain or IP you throw at it
|
|
39
|
+
- Contacts the internet (politely) for geo intel
|
|
40
|
+
- Drops a sweet, interactive map
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## ✨ Features
|
|
45
|
+
|
|
46
|
+
- Lookup **IP addresses** or **domains** like a pro hacker wannabe
|
|
47
|
+
- Detects your public IP like "hi, it's me"
|
|
48
|
+
- Maps exact-ish coordinates using [ipinfo.io](https://ipinfo.io)
|
|
49
|
+
- Generates a **live HTML map** with red circle vibes
|
|
50
|
+
- Dependency check? Yup — it acts like a cool installer
|
|
51
|
+
- Quietly avoids private IPs (don’t be that guy)
|
|
52
|
+
- Clean, modular CLI with argparse support
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🛠️ Requirements
|
|
57
|
+
|
|
58
|
+
- Python 3.7+
|
|
59
|
+
- Packages: `requests`, `folium`, ... (or let the script install it for you!)
|
|
60
|
+
- A totally-free `IPINFO_TOKEN` (get it [here](https://ipinfo.io/signup))
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 🚀 Run It Like a Legend
|
|
65
|
+
|
|
66
|
+
use pip !
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install yougotmapped
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Clone the repo
|
|
74
|
+
git clone https://github.com/Zynk-dot/YouGotMapped.git
|
|
75
|
+
cd YouGotMapped
|
|
76
|
+
|
|
77
|
+
# Option 1: Set token temporarily
|
|
78
|
+
export IPINFO_TOKEN=your_ipinfo_token
|
|
79
|
+
|
|
80
|
+
# Option 2: Let the script prompt you and save it to .env
|
|
81
|
+
|
|
82
|
+
# Run the thing
|
|
83
|
+
$ python3 yougotmapped.py
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then follow the prompts like a civilized hacker. You can:
|
|
87
|
+
- Press Enter to map **your own IP** (hello, paranoia)
|
|
88
|
+
- Or enter someone else's... 👀 (just be cool about it)
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 🧪 What You Get
|
|
93
|
+
|
|
94
|
+
- A readout of city, region, country, and more
|
|
95
|
+
- A *Google Maps-esque* HTML file you can open in your browser
|
|
96
|
+
- Optional delete at the end (for sneaky folks)
|
|
97
|
+
|
|
98
|
+
**File:** `ip_geolocation_map.html`
|
|
99
|
+
|
|
100
|
+
You can keep it. Frame it. Or trash it like a spy after a mission.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 🔐 Security Hints
|
|
105
|
+
|
|
106
|
+
- We only send your query to **ipinfo.io** — no creepy business
|
|
107
|
+
- Private IPs are blocked because that’s just weird
|
|
108
|
+
- API token is pulled from env vars (no hardcoded sins here)
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🙋 Who Made This?
|
|
113
|
+
|
|
114
|
+
> Created by a ghost.
|
|
115
|
+
> No name, no trace, no problem.
|
|
116
|
+
|
|
117
|
+
Contact? Nah, we don’t do that here.
|
|
118
|
+
If it breaks, fix it yourself — you're clearly smart enough to run this.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## ⭐ Why Star This Repo?
|
|
123
|
+
|
|
124
|
+
Because it's:
|
|
125
|
+
- Actually useful
|
|
126
|
+
- Small but mighty
|
|
127
|
+
- Funny
|
|
128
|
+
- And you’re already here reading this — go on, click ⭐
|
|
129
|
+
|
|
130
|
+
> This repo was cloned 30+ times before it even had a README. That’s how you know it slaps.
|
|
131
|
+
|
|
132
|
+
Thanks for checking this out.
|
|
133
|
+
You got mapped! 🗺️
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 🌍 YouGotMapped — IP Geolocation Mapper
|
|
2
|
+
|
|
3
|
+
Ever wondered where that weird IP pinging your router is *actually* from?
|
|
4
|
+
Or maybe you're just nosy (respect). Either way — this script's for you.
|
|
5
|
+
|
|
6
|
+
**YouGotMapped** is a sassy little Python tool that:
|
|
7
|
+
- Auto-fetches your IP (if you dare expose yourself)
|
|
8
|
+
- Accepts any domain or IP you throw at it
|
|
9
|
+
- Contacts the internet (politely) for geo intel
|
|
10
|
+
- Drops a sweet, interactive map
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## ✨ Features
|
|
15
|
+
|
|
16
|
+
- Lookup **IP addresses** or **domains** like a pro hacker wannabe
|
|
17
|
+
- Detects your public IP like "hi, it's me"
|
|
18
|
+
- Maps exact-ish coordinates using [ipinfo.io](https://ipinfo.io)
|
|
19
|
+
- Generates a **live HTML map** with red circle vibes
|
|
20
|
+
- Dependency check? Yup — it acts like a cool installer
|
|
21
|
+
- Quietly avoids private IPs (don’t be that guy)
|
|
22
|
+
- Clean, modular CLI with argparse support
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 🛠️ Requirements
|
|
27
|
+
|
|
28
|
+
- Python 3.7+
|
|
29
|
+
- Packages: `requests`, `folium`, ... (or let the script install it for you!)
|
|
30
|
+
- A totally-free `IPINFO_TOKEN` (get it [here](https://ipinfo.io/signup))
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🚀 Run It Like a Legend
|
|
35
|
+
|
|
36
|
+
use pip !
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install yougotmapped
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Clone the repo
|
|
44
|
+
git clone https://github.com/Zynk-dot/YouGotMapped.git
|
|
45
|
+
cd YouGotMapped
|
|
46
|
+
|
|
47
|
+
# Option 1: Set token temporarily
|
|
48
|
+
export IPINFO_TOKEN=your_ipinfo_token
|
|
49
|
+
|
|
50
|
+
# Option 2: Let the script prompt you and save it to .env
|
|
51
|
+
|
|
52
|
+
# Run the thing
|
|
53
|
+
$ python3 yougotmapped.py
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Then follow the prompts like a civilized hacker. You can:
|
|
57
|
+
- Press Enter to map **your own IP** (hello, paranoia)
|
|
58
|
+
- Or enter someone else's... 👀 (just be cool about it)
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 🧪 What You Get
|
|
63
|
+
|
|
64
|
+
- A readout of city, region, country, and more
|
|
65
|
+
- A *Google Maps-esque* HTML file you can open in your browser
|
|
66
|
+
- Optional delete at the end (for sneaky folks)
|
|
67
|
+
|
|
68
|
+
**File:** `ip_geolocation_map.html`
|
|
69
|
+
|
|
70
|
+
You can keep it. Frame it. Or trash it like a spy after a mission.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🔐 Security Hints
|
|
75
|
+
|
|
76
|
+
- We only send your query to **ipinfo.io** — no creepy business
|
|
77
|
+
- Private IPs are blocked because that’s just weird
|
|
78
|
+
- API token is pulled from env vars (no hardcoded sins here)
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 🙋 Who Made This?
|
|
83
|
+
|
|
84
|
+
> Created by a ghost.
|
|
85
|
+
> No name, no trace, no problem.
|
|
86
|
+
|
|
87
|
+
Contact? Nah, we don’t do that here.
|
|
88
|
+
If it breaks, fix it yourself — you're clearly smart enough to run this.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## ⭐ Why Star This Repo?
|
|
93
|
+
|
|
94
|
+
Because it's:
|
|
95
|
+
- Actually useful
|
|
96
|
+
- Small but mighty
|
|
97
|
+
- Funny
|
|
98
|
+
- And you’re already here reading this — go on, click ⭐
|
|
99
|
+
|
|
100
|
+
> This repo was cloned 30+ times before it even had a README. That’s how you know it slaps.
|
|
101
|
+
|
|
102
|
+
Thanks for checking this out.
|
|
103
|
+
You got mapped! 🗺️
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="yougotmapped",
|
|
5
|
+
version="1.0.0",
|
|
6
|
+
packages=find_packages(),
|
|
7
|
+
include_package_data=True,
|
|
8
|
+
install_requires=[
|
|
9
|
+
"requests",
|
|
10
|
+
"folium",
|
|
11
|
+
"python-dotenv",
|
|
12
|
+
"ping3"
|
|
13
|
+
],
|
|
14
|
+
entry_points={
|
|
15
|
+
"console_scripts": [
|
|
16
|
+
"yougotmapped = yougotmapped.cli:main"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
author="diputs",
|
|
20
|
+
author_email="diputs-sudo@proton.me",
|
|
21
|
+
description="A terminal tool to map IPs and domains with style.",
|
|
22
|
+
long_description=open("README.md").read(),
|
|
23
|
+
long_description_content_type="text/markdown",
|
|
24
|
+
url="https://github.com/diputs-sudo/YouGotMapped",
|
|
25
|
+
license="MIT",
|
|
26
|
+
classifiers=[
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
"License :: OSI Approved :: MIT License",
|
|
29
|
+
"Operating System :: OS Independent",
|
|
30
|
+
],
|
|
31
|
+
python_requires=">=3.7",
|
|
32
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import argparse
|
|
4
|
+
import ipaddress
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from yougotmapped.utils.dependencies import check_dependencies
|
|
9
|
+
from yougotmapped.utils.network import get_public_ip, get_geolocation, resolve_domain_to_ip
|
|
10
|
+
from yougotmapped.utils.mapping import plot_ip_location, plot_multiple_ip_locations
|
|
11
|
+
from yougotmapped.utils.token import get_api_token
|
|
12
|
+
from yougotmapped.utils.ping import ping_target
|
|
13
|
+
from yougotmapped.utils.trace import run_traceroute
|
|
14
|
+
from yougotmapped.utils.anonymity import detect_anonymity, format_anonymity_result
|
|
15
|
+
from yougotmapped.utils.output import write_formatted_output
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main():
|
|
19
|
+
parser = argparse.ArgumentParser(description="Geolocate one or more IPs/domains and generate an interactive map.")
|
|
20
|
+
parser.add_argument('-i', '--ip', nargs='*', help="One or more IPs/domains separated by space")
|
|
21
|
+
parser.add_argument('-f', '--file', type=str, help="Path to a file containing IPs/domains (one per line)")
|
|
22
|
+
parser.add_argument('-p', '--ping', action='store_true', help="Ping each IP or domain and show latency")
|
|
23
|
+
parser.add_argument('-t', '--trace', action='store_true', help="Show traceroute to each IP or domain")
|
|
24
|
+
parser.add_argument('-c', '--hidecheck', action='store_true', help="Check if the IP is a Tor exit node or VPN")
|
|
25
|
+
parser.add_argument('-o', '--output', type=str, help="Specify output file or use format shorthand (e.g., f:csv, f:json, f:normal)")
|
|
26
|
+
parser.add_argument('--no-map', action='store_true', help="Do not generate a map")
|
|
27
|
+
parser.add_argument('--delete-map', action='store_true', help="Delete the map after generating")
|
|
28
|
+
args = parser.parse_args()
|
|
29
|
+
|
|
30
|
+
check_dependencies()
|
|
31
|
+
|
|
32
|
+
API_TOKEN = get_api_token()
|
|
33
|
+
if not API_TOKEN:
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
targets = []
|
|
37
|
+
|
|
38
|
+
if args.ip:
|
|
39
|
+
targets.extend(args.ip)
|
|
40
|
+
|
|
41
|
+
if args.file:
|
|
42
|
+
try:
|
|
43
|
+
with open(args.file, 'r') as f:
|
|
44
|
+
targets.extend(line.strip() for line in f if line.strip())
|
|
45
|
+
except FileNotFoundError:
|
|
46
|
+
print(f"File not found: {args.file}")
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
if not targets:
|
|
50
|
+
print("No IP or file input provided. Defaulting to public IP lookup.")
|
|
51
|
+
ip_or_domain = get_public_ip()
|
|
52
|
+
if not ip_or_domain:
|
|
53
|
+
print("Could not determine your public IP.")
|
|
54
|
+
return
|
|
55
|
+
targets = [ip_or_domain]
|
|
56
|
+
|
|
57
|
+
geolocated = []
|
|
58
|
+
full_results = []
|
|
59
|
+
|
|
60
|
+
for target in targets:
|
|
61
|
+
target_result = {}
|
|
62
|
+
try:
|
|
63
|
+
ipaddress.ip_address(target)
|
|
64
|
+
ip_or_domain = target
|
|
65
|
+
except ValueError:
|
|
66
|
+
resolved_ip = resolve_domain_to_ip(target)
|
|
67
|
+
if resolved_ip:
|
|
68
|
+
ip_or_domain = resolved_ip
|
|
69
|
+
else:
|
|
70
|
+
print(f"Skipping unresolved domain: {target}")
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
print(f"Looking up location for {target}...")
|
|
74
|
+
data = get_geolocation(ip_or_domain, API_TOKEN)
|
|
75
|
+
if data:
|
|
76
|
+
geolocated.append(data)
|
|
77
|
+
target_result.update(data)
|
|
78
|
+
print("---")
|
|
79
|
+
for key in ['ip', 'hostname', 'city', 'region', 'country', 'loc', 'org', 'postal', 'timezone']:
|
|
80
|
+
print(f"{key.title()}: {data.get(key, 'N/A')}")
|
|
81
|
+
|
|
82
|
+
if args.ping:
|
|
83
|
+
print("\n[ PING RESULT ]")
|
|
84
|
+
ping_result = ping_target(target)
|
|
85
|
+
print(ping_result)
|
|
86
|
+
target_result["ping"] = ping_result
|
|
87
|
+
|
|
88
|
+
if args.trace:
|
|
89
|
+
print("\n[ TRACEROUTE RESULT ]")
|
|
90
|
+
trace_output = run_traceroute(target)
|
|
91
|
+
print(trace_output)
|
|
92
|
+
target_result["traceroute"] = trace_output
|
|
93
|
+
|
|
94
|
+
if args.hidecheck:
|
|
95
|
+
print("\n[ ANONYMITY CHECK ]")
|
|
96
|
+
anonymity = detect_anonymity(data)
|
|
97
|
+
format_anonymity_result(anonymity)
|
|
98
|
+
target_result["anonymity"] = anonymity
|
|
99
|
+
|
|
100
|
+
print("---")
|
|
101
|
+
full_results.append(target_result)
|
|
102
|
+
else:
|
|
103
|
+
print(f"Failed to get location data for {target}.")
|
|
104
|
+
|
|
105
|
+
# --- Output & Summary ---
|
|
106
|
+
map_saved = False
|
|
107
|
+
map_path = Path("ip_geolocation_map.html").resolve()
|
|
108
|
+
log_path = None
|
|
109
|
+
|
|
110
|
+
if not args.no_map and geolocated:
|
|
111
|
+
if len(geolocated) == 1:
|
|
112
|
+
m = plot_ip_location(geolocated[0], color="red")
|
|
113
|
+
|
|
114
|
+
if args.trace and isinstance(trace_output, str):
|
|
115
|
+
lines = trace_output.strip().split("\n")
|
|
116
|
+
for line in reversed(lines):
|
|
117
|
+
if "(" in line and ")" in line:
|
|
118
|
+
last_ip = line.split()[1]
|
|
119
|
+
try:
|
|
120
|
+
ipaddress.ip_address(last_ip)
|
|
121
|
+
last_data = get_geolocation(last_ip, API_TOKEN)
|
|
122
|
+
if last_data:
|
|
123
|
+
plot_ip_location(last_data, color="blue", map_object=m)
|
|
124
|
+
except Exception:
|
|
125
|
+
pass
|
|
126
|
+
break
|
|
127
|
+
if m:
|
|
128
|
+
m.save(str(map_path))
|
|
129
|
+
map_saved = True
|
|
130
|
+
|
|
131
|
+
elif len(geolocated) > 1:
|
|
132
|
+
plot_multiple_ip_locations(geolocated)
|
|
133
|
+
map_saved = True
|
|
134
|
+
|
|
135
|
+
if args.delete_map:
|
|
136
|
+
try:
|
|
137
|
+
os.remove(map_path)
|
|
138
|
+
map_saved = False
|
|
139
|
+
except FileNotFoundError:
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
if args.output:
|
|
143
|
+
os.makedirs("logs", exist_ok=True)
|
|
144
|
+
now = datetime.now()
|
|
145
|
+
date_str = now.strftime("%m-%d-%y")
|
|
146
|
+
time_str = now.strftime("%H-%M")
|
|
147
|
+
|
|
148
|
+
if args.output.startswith("f:"):
|
|
149
|
+
fmt_type = args.output[2:].lower()
|
|
150
|
+
ext = {"json": "json", "csv": "csv"}.get(fmt_type, "txt")
|
|
151
|
+
target_name = targets[0].replace(":", "-").replace("/", "-")
|
|
152
|
+
filename = f"{target_name}--{date_str}--{time_str}--YouGotMapped.{ext}"
|
|
153
|
+
else:
|
|
154
|
+
filename = args.output
|
|
155
|
+
fmt_type = filename.split('.')[-1].lower()
|
|
156
|
+
if fmt_type not in ["json", "csv", "txt"]:
|
|
157
|
+
fmt_type = "normal"
|
|
158
|
+
|
|
159
|
+
log_path = Path("logs") / filename
|
|
160
|
+
write_formatted_output(full_results, str(log_path), fmt_type=fmt_type)
|
|
161
|
+
log_path = log_path.resolve()
|
|
162
|
+
|
|
163
|
+
# Final summary
|
|
164
|
+
if map_saved or log_path:
|
|
165
|
+
print("\n----- OUTPUT SUMMARY -----")
|
|
166
|
+
if map_saved:
|
|
167
|
+
print(f"Map Location: {map_path}")
|
|
168
|
+
print(f"Map URL: file://{map_path}")
|
|
169
|
+
if log_path:
|
|
170
|
+
print(f"Log File: {log_path}")
|
|
171
|
+
print(f"Log URL: file://{log_path}")
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
if __name__ == "__main__":
|
|
175
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# utils/anonymity.py
|
|
2
|
+
import requests
|
|
3
|
+
import socket
|
|
4
|
+
|
|
5
|
+
TOR_EXIT_LIST = "https://check.torproject.org/torbulkexitlist"
|
|
6
|
+
|
|
7
|
+
VPN_KEYWORDS = [
|
|
8
|
+
"vpn", "m247", "nord", "express", "ovh", "digitalocean", "linode",
|
|
9
|
+
"datacamp", "host", "colo", "server", "vultr", "heficed", "leaseweb"
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def is_tor_exit_node(ip):
|
|
14
|
+
try:
|
|
15
|
+
response = requests.get(TOR_EXIT_LIST, timeout=5)
|
|
16
|
+
exit_nodes = response.text.strip().splitlines()
|
|
17
|
+
return ip in exit_nodes
|
|
18
|
+
except Exception:
|
|
19
|
+
return False
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def detect_anonymity(ip_data):
|
|
23
|
+
org = ip_data.get("org", "").lower()
|
|
24
|
+
hostname = ip_data.get("hostname", "").lower()
|
|
25
|
+
ip = ip_data.get("ip")
|
|
26
|
+
|
|
27
|
+
tor = is_tor_exit_node(ip)
|
|
28
|
+
vpn = any(keyword in org or keyword in hostname for keyword in VPN_KEYWORDS)
|
|
29
|
+
|
|
30
|
+
result = {
|
|
31
|
+
"ip": ip,
|
|
32
|
+
"tor": tor,
|
|
33
|
+
"vpn": vpn,
|
|
34
|
+
"org": org,
|
|
35
|
+
"hostname": hostname,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def format_anonymity_result(result):
|
|
42
|
+
ip = result["ip"]
|
|
43
|
+
print(f"IP: {ip}")
|
|
44
|
+
print(f"Org: {result['org'] or 'N/A'}")
|
|
45
|
+
print(f"Hostname: {result['hostname'] or 'N/A'}")
|
|
46
|
+
if result['tor']:
|
|
47
|
+
print("Tor Exit Node: YES")
|
|
48
|
+
else:
|
|
49
|
+
print("Tor Exit Node: No")
|
|
50
|
+
if result['vpn']:
|
|
51
|
+
print("VPN / Proxy Suspected: YES")
|
|
52
|
+
else:
|
|
53
|
+
print("VPN / Proxy Suspected: No")
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# utils/dependencies.py
|
|
2
|
+
import importlib.util
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_dependencies():
|
|
8
|
+
required = {
|
|
9
|
+
"requests": "requests",
|
|
10
|
+
"folium": "folium",
|
|
11
|
+
"ping3": "ping3",
|
|
12
|
+
"python-dotenv": "dotenv"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
print("\nChecking dependencies:\n")
|
|
16
|
+
|
|
17
|
+
for package_name, module_name in required.items():
|
|
18
|
+
spec = importlib.util.find_spec(module_name)
|
|
19
|
+
if spec is not None:
|
|
20
|
+
print(f" [OK] {package_name} found")
|
|
21
|
+
else:
|
|
22
|
+
print(f" [MISSING] {package_name} not found")
|
|
23
|
+
choice = input(f" Install '{package_name}' now? (yes/no): ").strip().lower()
|
|
24
|
+
if choice in ['yes', 'y']:
|
|
25
|
+
try:
|
|
26
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", package_name])
|
|
27
|
+
print(f" '{package_name}' successfully installed\n")
|
|
28
|
+
except subprocess.CalledProcessError:
|
|
29
|
+
print(f" Failed to install '{package_name}'. Please install manually.")
|
|
30
|
+
sys.exit(1)
|
|
31
|
+
else:
|
|
32
|
+
print(f" Cannot continue without '{package_name}'. Exiting.")
|
|
33
|
+
sys.exit(1)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# utils/mapping.py
|
|
2
|
+
import folium
|
|
3
|
+
|
|
4
|
+
def plot_ip_location(ip_data, color='red', map_object=None):
|
|
5
|
+
if 'loc' not in ip_data:
|
|
6
|
+
print("Location data not available.")
|
|
7
|
+
return
|
|
8
|
+
|
|
9
|
+
latitude, longitude = map(float, ip_data['loc'].split(','))
|
|
10
|
+
|
|
11
|
+
m = map_object if map_object else folium.Map(location=[latitude, longitude], zoom_start=12)
|
|
12
|
+
|
|
13
|
+
folium.Marker(
|
|
14
|
+
[latitude, longitude],
|
|
15
|
+
popup=f"IP: {ip_data.get('ip', 'N/A')}\nCity: {ip_data.get('city', 'N/A')}\nRegion: {ip_data.get('region', 'N/A')}\nCountry: {ip_data.get('country', 'N/A')}",
|
|
16
|
+
icon=folium.Icon(color=color)
|
|
17
|
+
).add_to(m)
|
|
18
|
+
|
|
19
|
+
folium.Circle(
|
|
20
|
+
radius=10000,
|
|
21
|
+
location=[latitude, longitude],
|
|
22
|
+
color=color,
|
|
23
|
+
fill=True,
|
|
24
|
+
fill_color=color,
|
|
25
|
+
fill_opacity=0.2,
|
|
26
|
+
popup="Approximate Area"
|
|
27
|
+
).add_to(m)
|
|
28
|
+
|
|
29
|
+
return m
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def plot_multiple_ip_locations(ip_data_list):
|
|
33
|
+
if not ip_data_list:
|
|
34
|
+
print("No valid IP data to plot.")
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
center_data = next((d for d in ip_data_list if 'loc' in d), None)
|
|
38
|
+
if not center_data:
|
|
39
|
+
print("No valid location data found in input list.")
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
latitude, longitude = map(float, center_data['loc'].split(','))
|
|
43
|
+
m = folium.Map(location=[latitude, longitude], zoom_start=2)
|
|
44
|
+
|
|
45
|
+
for data in ip_data_list:
|
|
46
|
+
if 'loc' not in data:
|
|
47
|
+
continue
|
|
48
|
+
lat, lon = map(float, data['loc'].split(','))
|
|
49
|
+
folium.Marker(
|
|
50
|
+
[lat, lon],
|
|
51
|
+
popup=f"IP: {data.get('ip', 'N/A')}\nCity: {data.get('city', 'N/A')}\nRegion: {data.get('region', 'N/A')}\nCountry: {data.get('country', 'N/A')}",
|
|
52
|
+
icon=folium.Icon(color='red')
|
|
53
|
+
).add_to(m)
|
|
54
|
+
|
|
55
|
+
folium.Circle(
|
|
56
|
+
radius=10000,
|
|
57
|
+
location=[lat, lon],
|
|
58
|
+
color='red',
|
|
59
|
+
fill=True,
|
|
60
|
+
fill_color='red',
|
|
61
|
+
fill_opacity=0.2,
|
|
62
|
+
popup="Approximate Area"
|
|
63
|
+
).add_to(m)
|
|
64
|
+
|
|
65
|
+
m.save('ip_geolocation_map.html')
|
|
66
|
+
print("Map saved with multiple IPs as 'ip_geolocation_map.html'")
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# utils/network.py
|
|
2
|
+
import requests
|
|
3
|
+
import ipaddress
|
|
4
|
+
import socket
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_public_ip():
|
|
8
|
+
try:
|
|
9
|
+
response = requests.get('https://api.ipify.org')
|
|
10
|
+
response.raise_for_status()
|
|
11
|
+
return response.text
|
|
12
|
+
except requests.exceptions.RequestException as e:
|
|
13
|
+
print(f"Error fetching public IP: {e}")
|
|
14
|
+
return None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_geolocation(ip_or_domain, api_token):
|
|
18
|
+
url = f"https://ipinfo.io/{ip_or_domain}/json"
|
|
19
|
+
params = {'token': api_token} if api_token else {}
|
|
20
|
+
try:
|
|
21
|
+
response = requests.get(url, params=params)
|
|
22
|
+
response.raise_for_status()
|
|
23
|
+
return response.json()
|
|
24
|
+
except requests.exceptions.RequestException as e:
|
|
25
|
+
print(f"Error fetching geolocation data: {e}")
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def resolve_domain_to_ip(domain):
|
|
30
|
+
try:
|
|
31
|
+
return socket.gethostbyname(domain)
|
|
32
|
+
except socket.gaierror:
|
|
33
|
+
print(f"Could not resolve domain: {domain}")
|
|
34
|
+
return None
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# utils/output.py
|
|
2
|
+
import json
|
|
3
|
+
import csv
|
|
4
|
+
from io import StringIO
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def format_as_normal(data):
|
|
8
|
+
output = []
|
|
9
|
+
for d in data:
|
|
10
|
+
lines = []
|
|
11
|
+
for key, value in d.items():
|
|
12
|
+
if isinstance(value, dict):
|
|
13
|
+
lines.append(f"{key.title()}:")
|
|
14
|
+
for sub_key, sub_val in value.items():
|
|
15
|
+
lines.append(f" {sub_key.title()}: {sub_val}")
|
|
16
|
+
else:
|
|
17
|
+
lines.append(f"{key.title()}: {value}")
|
|
18
|
+
output.append("\n".join(lines))
|
|
19
|
+
output.append("\n" + "-" * 40 + "\n")
|
|
20
|
+
return "\n".join(output)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def flatten_for_csv(entry):
|
|
24
|
+
"""
|
|
25
|
+
Flatten nested dictionaries for CSV.
|
|
26
|
+
For example: {"anonymity": {"vpn": False}} -> {"anonymity_vpn": False}
|
|
27
|
+
"""
|
|
28
|
+
flat = {}
|
|
29
|
+
for key, value in entry.items():
|
|
30
|
+
if isinstance(value, dict):
|
|
31
|
+
for sub_key, sub_val in value.items():
|
|
32
|
+
flat[f"{key}_{sub_key}"] = sub_val
|
|
33
|
+
else:
|
|
34
|
+
flat[key] = value
|
|
35
|
+
return flat
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def format_as_csv(data):
|
|
39
|
+
if not data:
|
|
40
|
+
return ""
|
|
41
|
+
flat_data = [flatten_for_csv(d) for d in data]
|
|
42
|
+
# Collect all possible fields across entries
|
|
43
|
+
fieldnames = sorted({key for d in flat_data for key in d.keys()})
|
|
44
|
+
output = StringIO()
|
|
45
|
+
writer = csv.DictWriter(output, fieldnames=fieldnames)
|
|
46
|
+
writer.writeheader()
|
|
47
|
+
for d in flat_data:
|
|
48
|
+
writer.writerow(d)
|
|
49
|
+
return output.getvalue()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def format_as_json(data):
|
|
53
|
+
return json.dumps(data, indent=4)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def write_formatted_output(data, file_path, fmt_type="normal"):
|
|
57
|
+
fmt_type = fmt_type.lower()
|
|
58
|
+
if fmt_type == "csv":
|
|
59
|
+
formatted = format_as_csv(data)
|
|
60
|
+
elif fmt_type == "json":
|
|
61
|
+
formatted = format_as_json(data)
|
|
62
|
+
else:
|
|
63
|
+
formatted = format_as_normal(data)
|
|
64
|
+
|
|
65
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
66
|
+
f.write(formatted)
|
|
67
|
+
print(f"Output saved to {file_path} in {fmt_type.upper()} format.")
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# utils/pings.py
|
|
2
|
+
from ping3 import ping
|
|
3
|
+
import statistics
|
|
4
|
+
|
|
5
|
+
def classify_rtt_latency(latency):
|
|
6
|
+
if latency < 1:
|
|
7
|
+
return "LAN or loopback — same machine or local router"
|
|
8
|
+
elif latency < 5:
|
|
9
|
+
return "Local network — same building or direct fiber"
|
|
10
|
+
elif latency < 20:
|
|
11
|
+
return "Nearby region — very low-latency ISP link"
|
|
12
|
+
elif latency < 50:
|
|
13
|
+
return "Fast WAN — CDN, local data center, or strong routing"
|
|
14
|
+
elif latency < 100:
|
|
15
|
+
return "Typical internet — stable ISP-to-ISP connection"
|
|
16
|
+
elif latency < 200:
|
|
17
|
+
return "Remote server — possible transcontinental routing"
|
|
18
|
+
elif latency < 400:
|
|
19
|
+
return "High latency — distant, congested, or routed via relay"
|
|
20
|
+
else:
|
|
21
|
+
return "Unstable or suspicious — VPN, proxy, or degraded network"
|
|
22
|
+
|
|
23
|
+
def ping_target(host, count=4):
|
|
24
|
+
"""
|
|
25
|
+
Pings the given host and returns avg latency, loss %, estimated distance, and a basic label.
|
|
26
|
+
"""
|
|
27
|
+
latencies = []
|
|
28
|
+
|
|
29
|
+
for _ in range(count):
|
|
30
|
+
try:
|
|
31
|
+
delay = ping(host, timeout=1)
|
|
32
|
+
if delay:
|
|
33
|
+
latencies.append(delay)
|
|
34
|
+
except Exception:
|
|
35
|
+
continue
|
|
36
|
+
|
|
37
|
+
received = len(latencies)
|
|
38
|
+
lost = count - received
|
|
39
|
+
|
|
40
|
+
if received == 0:
|
|
41
|
+
return f"Ping to {host}: unreachable ({count} packets lost)"
|
|
42
|
+
|
|
43
|
+
avg_latency_ms = round(statistics.mean(latencies) * 1000, 2)
|
|
44
|
+
packet_loss = round((lost / count) * 100, 1)
|
|
45
|
+
|
|
46
|
+
# Go back to fast, rough RTT-based estimate: 200 km/ms
|
|
47
|
+
estimated_distance_km = round((avg_latency_ms / 2) * 200)
|
|
48
|
+
label = classify_rtt_latency(avg_latency_ms)
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
f"Ping to {host} ({count} packets):\n"
|
|
52
|
+
f" Avg Latency: {avg_latency_ms} ms\n"
|
|
53
|
+
f" Packet Loss: {packet_loss}%\n"
|
|
54
|
+
f" Est. Distance: ~{estimated_distance_km} km (RTT-based)\n"
|
|
55
|
+
f" Inference: {label}"
|
|
56
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# utils/token.py
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from dotenv import load_dotenv
|
|
5
|
+
|
|
6
|
+
def get_api_token():
|
|
7
|
+
# Force .env path to the installed package folder
|
|
8
|
+
env_path = Path(__file__).resolve().parent.parent / ".env"
|
|
9
|
+
load_dotenv(dotenv_path=env_path)
|
|
10
|
+
|
|
11
|
+
token = os.getenv("IPINFO_TOKEN")
|
|
12
|
+
if token:
|
|
13
|
+
return token
|
|
14
|
+
|
|
15
|
+
print("'IPINFO_TOKEN' environment variable not found.")
|
|
16
|
+
print("To use this tool, you need a free API token from ipinfo.io.")
|
|
17
|
+
print("Visit: https://ipinfo.io/signup")
|
|
18
|
+
token = input("Enter your IPInfo token: ").strip()
|
|
19
|
+
|
|
20
|
+
if token:
|
|
21
|
+
save = input("Would you like to save this token to a .env file for future runs? (yes/no): ").strip().lower()
|
|
22
|
+
if save in ['yes', 'y']:
|
|
23
|
+
try:
|
|
24
|
+
with open(env_path, "a") as env_file:
|
|
25
|
+
env_file.write(f"\nIPINFO_TOKEN={token}\n")
|
|
26
|
+
print("Token saved to .env file. Make sure to load it in your script using python-dotenv or similar.")
|
|
27
|
+
except Exception as e:
|
|
28
|
+
print(f"Error saving token: {e}")
|
|
29
|
+
return token
|
|
30
|
+
|
|
31
|
+
return None
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# utils/trace.py
|
|
2
|
+
import subprocess
|
|
3
|
+
import platform
|
|
4
|
+
import re
|
|
5
|
+
import ipaddress
|
|
6
|
+
from yougotmapped.utils.network import get_geolocation
|
|
7
|
+
|
|
8
|
+
def run_traceroute(host, max_hops=30, timeout=60):
|
|
9
|
+
system = platform.system()
|
|
10
|
+
if system == "Windows":
|
|
11
|
+
cmd = ["tracert", "-h", str(max_hops), host]
|
|
12
|
+
elif system in ["Linux", "Darwin"]:
|
|
13
|
+
cmd = ["traceroute", "-m", str(max_hops), "-w", "1", host]
|
|
14
|
+
else:
|
|
15
|
+
return f"Traceroute not supported on {system}"
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
|
19
|
+
return format_trace_output(result.stdout)
|
|
20
|
+
except subprocess.TimeoutExpired:
|
|
21
|
+
return f"Traceroute to {host} timed out after {timeout} seconds."
|
|
22
|
+
except FileNotFoundError:
|
|
23
|
+
return f"Traceroute command not found on this system."
|
|
24
|
+
except Exception as e:
|
|
25
|
+
return f"Traceroute failed: {e}"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def is_private_ip(ip):
|
|
29
|
+
try:
|
|
30
|
+
return ipaddress.ip_address(ip).is_private
|
|
31
|
+
except ValueError:
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def extract_ip_latency(line):
|
|
36
|
+
ip_match = re.findall(r"(\d+\.\d+\.\d+\.\d+)", line)
|
|
37
|
+
rtt_match = re.findall(r"(\d+\.\d+) ms", line)
|
|
38
|
+
return ip_match[0] if ip_match else None, rtt_match[0] if rtt_match else None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def format_trace_output(raw_output):
|
|
42
|
+
lines = raw_output.strip().split("\n")
|
|
43
|
+
formatted_lines = []
|
|
44
|
+
last_ip = None
|
|
45
|
+
|
|
46
|
+
for index, line in enumerate(lines):
|
|
47
|
+
ip, rtt = extract_ip_latency(line)
|
|
48
|
+
if not ip:
|
|
49
|
+
continue
|
|
50
|
+
|
|
51
|
+
label = "(Private)" if is_private_ip(ip) else extract_label(line)
|
|
52
|
+
formatted_lines.append(f"[{index+1}] {ip.ljust(18)} {label.ljust(30)} {rtt} ms")
|
|
53
|
+
last_ip = ip
|
|
54
|
+
|
|
55
|
+
# Append final geolocation if last IP is public
|
|
56
|
+
if last_ip and not is_private_ip(last_ip):
|
|
57
|
+
data = get_geolocation(last_ip, None)
|
|
58
|
+
if data:
|
|
59
|
+
geo_info = f" --> {data.get('city', 'N/A')}, {data.get('region', '')} ({data.get('org', 'N/A')})"
|
|
60
|
+
formatted_lines.append(geo_info)
|
|
61
|
+
|
|
62
|
+
return "\n".join(formatted_lines)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def extract_label(line):
|
|
66
|
+
parts = line.split()
|
|
67
|
+
for part in parts:
|
|
68
|
+
if any(ext in part for ext in [".com", ".net", ".org"]):
|
|
69
|
+
return f"({part})"
|
|
70
|
+
return "(Public)"
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yougotmapped
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A terminal tool to map IPs and domains with style.
|
|
5
|
+
Home-page: https://github.com/diputs-sudo/YouGotMapped
|
|
6
|
+
Author: diputs
|
|
7
|
+
Author-email: diputs-sudo@proton.me
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.7
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests
|
|
16
|
+
Requires-Dist: folium
|
|
17
|
+
Requires-Dist: python-dotenv
|
|
18
|
+
Requires-Dist: ping3
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: author-email
|
|
21
|
+
Dynamic: classifier
|
|
22
|
+
Dynamic: description
|
|
23
|
+
Dynamic: description-content-type
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
30
|
+
|
|
31
|
+
# 🌍 YouGotMapped — IP Geolocation Mapper
|
|
32
|
+
|
|
33
|
+
Ever wondered where that weird IP pinging your router is *actually* from?
|
|
34
|
+
Or maybe you're just nosy (respect). Either way — this script's for you.
|
|
35
|
+
|
|
36
|
+
**YouGotMapped** is a sassy little Python tool that:
|
|
37
|
+
- Auto-fetches your IP (if you dare expose yourself)
|
|
38
|
+
- Accepts any domain or IP you throw at it
|
|
39
|
+
- Contacts the internet (politely) for geo intel
|
|
40
|
+
- Drops a sweet, interactive map
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## ✨ Features
|
|
45
|
+
|
|
46
|
+
- Lookup **IP addresses** or **domains** like a pro hacker wannabe
|
|
47
|
+
- Detects your public IP like "hi, it's me"
|
|
48
|
+
- Maps exact-ish coordinates using [ipinfo.io](https://ipinfo.io)
|
|
49
|
+
- Generates a **live HTML map** with red circle vibes
|
|
50
|
+
- Dependency check? Yup — it acts like a cool installer
|
|
51
|
+
- Quietly avoids private IPs (don’t be that guy)
|
|
52
|
+
- Clean, modular CLI with argparse support
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🛠️ Requirements
|
|
57
|
+
|
|
58
|
+
- Python 3.7+
|
|
59
|
+
- Packages: `requests`, `folium`, ... (or let the script install it for you!)
|
|
60
|
+
- A totally-free `IPINFO_TOKEN` (get it [here](https://ipinfo.io/signup))
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 🚀 Run It Like a Legend
|
|
65
|
+
|
|
66
|
+
use pip !
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install yougotmapped
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Clone the repo
|
|
74
|
+
git clone https://github.com/Zynk-dot/YouGotMapped.git
|
|
75
|
+
cd YouGotMapped
|
|
76
|
+
|
|
77
|
+
# Option 1: Set token temporarily
|
|
78
|
+
export IPINFO_TOKEN=your_ipinfo_token
|
|
79
|
+
|
|
80
|
+
# Option 2: Let the script prompt you and save it to .env
|
|
81
|
+
|
|
82
|
+
# Run the thing
|
|
83
|
+
$ python3 yougotmapped.py
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then follow the prompts like a civilized hacker. You can:
|
|
87
|
+
- Press Enter to map **your own IP** (hello, paranoia)
|
|
88
|
+
- Or enter someone else's... 👀 (just be cool about it)
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 🧪 What You Get
|
|
93
|
+
|
|
94
|
+
- A readout of city, region, country, and more
|
|
95
|
+
- A *Google Maps-esque* HTML file you can open in your browser
|
|
96
|
+
- Optional delete at the end (for sneaky folks)
|
|
97
|
+
|
|
98
|
+
**File:** `ip_geolocation_map.html`
|
|
99
|
+
|
|
100
|
+
You can keep it. Frame it. Or trash it like a spy after a mission.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 🔐 Security Hints
|
|
105
|
+
|
|
106
|
+
- We only send your query to **ipinfo.io** — no creepy business
|
|
107
|
+
- Private IPs are blocked because that’s just weird
|
|
108
|
+
- API token is pulled from env vars (no hardcoded sins here)
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🙋 Who Made This?
|
|
113
|
+
|
|
114
|
+
> Created by a ghost.
|
|
115
|
+
> No name, no trace, no problem.
|
|
116
|
+
|
|
117
|
+
Contact? Nah, we don’t do that here.
|
|
118
|
+
If it breaks, fix it yourself — you're clearly smart enough to run this.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## ⭐ Why Star This Repo?
|
|
123
|
+
|
|
124
|
+
Because it's:
|
|
125
|
+
- Actually useful
|
|
126
|
+
- Small but mighty
|
|
127
|
+
- Funny
|
|
128
|
+
- And you’re already here reading this — go on, click ⭐
|
|
129
|
+
|
|
130
|
+
> This repo was cloned 30+ times before it even had a README. That’s how you know it slaps.
|
|
131
|
+
|
|
132
|
+
Thanks for checking this out.
|
|
133
|
+
You got mapped! 🗺️
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
setup.py
|
|
5
|
+
yougotmapped/__init__.py
|
|
6
|
+
yougotmapped/cli.py
|
|
7
|
+
yougotmapped.egg-info/PKG-INFO
|
|
8
|
+
yougotmapped.egg-info/SOURCES.txt
|
|
9
|
+
yougotmapped.egg-info/dependency_links.txt
|
|
10
|
+
yougotmapped.egg-info/entry_points.txt
|
|
11
|
+
yougotmapped.egg-info/requires.txt
|
|
12
|
+
yougotmapped.egg-info/top_level.txt
|
|
13
|
+
yougotmapped/utils/__init__.py
|
|
14
|
+
yougotmapped/utils/anonymity.py
|
|
15
|
+
yougotmapped/utils/dependencies.py
|
|
16
|
+
yougotmapped/utils/mapping.py
|
|
17
|
+
yougotmapped/utils/network.py
|
|
18
|
+
yougotmapped/utils/output.py
|
|
19
|
+
yougotmapped/utils/ping.py
|
|
20
|
+
yougotmapped/utils/token.py
|
|
21
|
+
yougotmapped/utils/trace.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
yougotmapped
|