forked from JMousqueton/ransomware.live
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathworldmap.py
87 lines (69 loc) · 2.97 KB
/
worldmap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import pandas as pd
import json
from mypycountries import get_coordinates, get_country_name # https://github.com/JMousqueton/MyPyCountries
import folium
from sharedutils import stdlog, dbglog, errlog
from datetime import datetime
import os
file_path = './docs/map.md'
current_year = datetime.now().year
# Load JSON data from file
stdlog('Reading posts.json ...')
with open('./posts.json', 'r') as file:
data = json.load(file)
# Convert data into a DataFrame
df = pd.DataFrame(data)
# Convert 'date' column to datetime, assuming the format is 'YYYY-MM-DD HH:MM:SS.ssssss'
df['discovered'] = pd.to_datetime(df['discovered'], errors='coerce')
stdlog('Filtering victims')
# Filter for rows where the year is current_year
df_currentyear = df[df['discovered'].dt.year == current_year]
# Filter rows where 'country' is not None or empty
filtered_df = df_currentyear[df_currentyear['country'].notna() & (df_currentyear['country'] != '')].copy()
# Aggregate data by country code, counting entries per country code
country_counts = filtered_df['country'].value_counts().reset_index()
country_counts.columns = ['country', 'count']
stdlog('Getting geocoding ...')
# Apply geocoding
country_counts['coords'] = country_counts['country'].apply(get_coordinates)
title_html = '''
<h3 align="center" style="font-size:16px"><b>© {} <a href="https://www.ransomware.live/">Ransomware.live</a></b></h3>
'''.format(current_year)
stdlog('Initialize Map')
# Create a map
map = folium.Map(location=[20, 0], zoom_start=2)
map.get_root().html.add_child(folium.Element(title_html))
# Scaling factor for the radius
scale_factor = 1
stdlog('Adding point on map ...')
# Add points to the map
for idx, row in country_counts.iterrows():
if row['coords'] is not None: # Ensure the coordinates are not None
lat, lon = row['coords']
if lat is not None and lon is not None: # Ensure both latitude and longitude are available
folium.CircleMarker(
location=[lat, lon],
radius=scale_factor * row['count']**0.5, # Scale radius based on square root of count
popup=f"<a href='https://www.ransomware.live/#/country/{row['country'].lower()}' target='_parent'>{get_country_name(row['country'])}</a>: {row['count']} victim(s)",
color='red',
fill=True,
fill_opacity=0.7
).add_to(map)
#print('--->',row['coords'])
else:
stdlog("2) Skipping " + row['country'] + " due to missing coordinates.")
else:
stdlog("2) Skipping " + row['country'] + " due to missing coordinates.")
# Save or show the map
stdlog('Writing Map ...')
map.save('docs/map.html')
stdlog('Writing markdown file ...')
current_datetime = datetime.now().isoformat()
content = f"""
### 🗺️ Worldmap for ransomware's attacks in {current_year}
[filename](map.html ':include')
_Last update: {current_datetime}_
"""
with open(file_path, 'w') as file:
file.write(content)
stdlog('done')