from django.http import HttpResponse, HttpResponseBadRequest from django.shortcuts import redirect, render from django.urls import reverse from .models import Organization import requests import pickle import qrcode import json import random from .utils import to_pickle, from_pickle, remove_dup_dict_in_list, get_org_by_id bot_name = "tfbbot" auth_link = "https://oauth.groupme.com/oauth/authorize?client_id=KbStJZciPGivvLuTN9XX6aXf6NHVcxDSiVR0wRC0cqVDuDfG" def login(request): return redirect(auth_link) def add_organization_flow_select(request): user_group_data = from_pickle(request.session["groupme_groups_pickle"]) user_group_data = user_group_data["response"] if request.method == "GET": rendered_groups = [] rendered_users = [] for group in user_group_data: our_id = request.session["groupme_id"] for user in group["members"]: # check if we're an admin if user["user_id"] == our_id: if "admin" in user["roles"]: # we are an admin rendered_groups.append({ "name": group["name"], "id": group["group_id"] }) for user in group["members"]: rendered_users.append({ "name": user["name"], "id": user["user_id"] }) break rendered_users = remove_dup_dict_in_list(rendered_users) # sort users by name rendered_users = sorted(rendered_users, key=lambda x: x["name"].lower()) context = { "request": request, "title": "Add organization", "groups": rendered_groups, "users": rendered_users } return render(request, "create_organization.html", context) elif request.method == "POST": name = request.POST["name"] users = [i[2:] for i in request.POST.keys() if i.startswith("u_")] groups = [i[2:] for i in request.POST.keys() if i.startswith("g_")] group_name_mapping = from_pickle(request.session["group_name_mapping"]) org = Organization() org.owner = request.session["groupme_id"] org.name = name org.trusted_users = "" org.channel_info = "" org.save() group_data_collected = [] for group in groups: group_data = { "gid": group } data = { "bot": { "name": bot_name, "group_id": group, "active": True, "callback_url": "https://marching.beepboop.systems/groupme/organization/{}/callback/{}".format( org.id, str(random.randint(1, 100000)) ), } } r = requests.post( "https://api.groupme.com/v3/bots?token={}".format( request.session["groupme_access_token"] ), data=json.dumps(data), headers={"Content-Type": "application/json"}, ) data = r.json() print(r.url) group_data["bot_id"] = data["response"]["bot"]["bot_id"] group_data["name"] = group_name_mapping[group_data["gid"]] group_data["role"] = "trusted" group_data_collected.append(group_data) user_data_collected = [] user_name_mappings = from_pickle(request.session["user_name_mapping"]) for user in users: try: username = user_name_mappings[user] except KeyError: username = "unknown" user_data = { "uid": user, "role": "trusted", "name": username, "number_messages": 0 } user_data_collected.append(user_data) org.trusted_users = to_pickle(user_data_collected) org.channel_info = to_pickle(group_data_collected) org.save() return redirect(reverse("view_organization", kwargs={"org_id": org.id})) def handle_oauth(request): request.session["groupme_access_token"] = request.GET.get('access_token') r = requests.get("https://api.groupme.com/v3/users/me?token={}".format( request.session["groupme_access_token"] )) data = r.json() request.session["groupme_id"] = data["response"]["id"] request.session["groupme_name"] = data["response"]["name"] r = requests.get("https://api.groupme.com/v3/groups?token={}&per_page=200".format( request.session["groupme_access_token"] )) request.session["groupme_groups_pickle"] = to_pickle(r.json()) request.session["logged_in"] = "yes" group_name_mapping = {} for group in r.json()["response"]: group_name_mapping[group["id"]] = group["name"] request.session["group_name_mapping"] = to_pickle(group_name_mapping) user_name_mapping = {} for group in r.json()["response"]: for user in group["members"]: user_name_mapping[user["id"]] = user["name"] user_name_mapping[data["response"]["id"]] = data["response"]["name"] request.session["user_name_mapping"] = to_pickle(user_name_mapping) try: if request.session["needs_redirect"]: response = redirect(reverse(request.session["needs_redirect"])) del request.session["needs_redirect"] return response except KeyError: pass return redirect(reverse("index")) def index(request): if "logged_in" in request.session: orgs = Organization.objects.filter(owner=request.session["groupme_id"]) return render(request, "index_auth.html", { "title": "Home", "request": request, "organizations": orgs, }) else: return render(request, "index_unauth.html", { "title": "Home", }) def refresh_group_data(request): return redirect(reverse("handle_oauth") + "?access_token={}".format( request.session["groupme_access_token"] )) def logout(request): if "logged_in" in request.session: request.session.flush() return render(request, "logged_out.html") else: return redirect(index) def view_organization(request, org_id): org = get_org_by_id(org_id) scheme = 'https' if request.is_secure() else 'http' hostname = request.get_host() if request.session["groupme_id"] == org.owner: org_channel_info = from_pickle(org.channel_info) org_trusted_users = from_pickle(org.trusted_users) return render(request, "view_organization.html", { "request": request, "org": org, "hostname": hostname, "scheme": scheme, "channels": org_channel_info, "users": org_trusted_users, }) else: pass # blow up def qr_code(request, org_id): org = get_org_by_id(org_id) scheme = 'https' if request.is_secure() else 'http' hostname = request.get_host() qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4, ) qr.add_data("{}://{}{}".format( scheme, hostname, reverse('add_channel_to_organization', args=[org.id]), )) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") resp = HttpResponse( headers={ "Content-Type": "image/png", } ) img.save(resp) return resp def add_channel_to_organization(request, org_id, trusted=False): if not request.session["groupme_access_token"]: request.session["needs_redirect"] = "add_channel_to_organization" return redirect(reverse("login")) org = get_org_by_id(org_id) if request.method == "GET": user_group_data = from_pickle(request.session["groupme_groups_pickle"])["response"] our_id = request.session["groupme_id"] groups_we_admin = [] for group in user_group_data: for user in group["members"]: # check if we're an admin if user["user_id"] == our_id: if "admin" in user["roles"]: # we are an admin groups_we_admin.append(group) return render(request, "add_channel_to_organization.html", { "groups": groups_we_admin, "org": org, "request": request, "trusted": trusted, }) elif request.method == "POST": group_name_mapping = from_pickle(request.session["group_name_mapping"]) org = get_org_by_id(org_id) groups = [i[2:] for i in request.POST.keys() if i.startswith("g_")] org_group_info = pickle.loads(bytes.fromhex(org.channel_info)) if not trusted: for group in org_group_info: if group["gid"] in groups and group["role"] != "trusted": # prune the groups groups.remove(group["gid"]) else: for index, group in enumerate(org_group_info): if group["gid"] in groups: org_group_info[index]["role"] = "trusted" to_add = [] # these are the unique groups for group in groups: if not trusted: data = { "bot": { "name": bot_name, "group_id": group, "active": True, } } else: data = { "bot": { "name": bot_name, "group_id": group, "active": True, "callback_url": "https://marching.beepboop.systems/groupme/organization/{}/callback/{}".format( org.id, str(random.randint(1, 100000)) ), } } r = requests.post( "https://api.groupme.com/v3/bots?token={}".format( request.session["groupme_access_token"] ), data=json.dumps(data), headers={"Content-Type": "application/json"}, ) data = r.json() if not trusted: to_add.append({ "gid": group, "bot_id": data["response"]["bot"]["bot_id"], "name": group_name_mapping[group], "role": "following", }) else: to_add.append({ "gid": group, "bot_id": data["response"]["bot"]["bot_id"], "name": group_name_mapping[group], "role": "trusted", }) org_group_info += to_add org.channel_info = pickle.dumps(org_group_info).hex() org.save() if request.session["groupme_id"] == org.owner: return redirect(reverse('view_organization', args=[org.id])) else: return render(request, "group_add_succeed.html", { "request": request }) def add_trusted_channel(request, org_id): return add_channel_to_organization(request, org_id, trusted=True) def delete_channel(request, org_id, chan): org = Organization.objects.filter(id__exact=org_id)[0] org_group_info = pickle.loads(bytes.fromhex(org.channel_info)) print(org_group_info) for index, channel in enumerate(org_group_info): print(index, channel) if channel["gid"] == chan: org_group_info.pop(index) break org.channel_info = pickle.dumps(org_group_info).hex() org.save() return redirect(reverse('view_organization', args=[org.id])) def demote_channel(request, org_id, chan): org = get_org_by_id(org_id) org_group_info = from_pickle(org.channel_info) for index, channel in enumerate(org_group_info): print(index, channel) if channel["gid"] == chan: org_group_info[index]["role"] = "following" break org.channel_info = to_pickle(org_group_info) org.save() return redirect(reverse('view_organization', args=[org.id])) def add_trusted_user(request, org_id): org = get_org_by_id(org_id) org_trusted_users = from_pickle(org.trusted_users) user_group_data = from_pickle(request.session["groupme_groups_pickle"]) user_group_data = user_group_data["response"] rendered_users = [] for group in user_group_data: our_id = request.session["groupme_id"] for user in group["members"]: # check if we're an admin if user["user_id"] == our_id: if "admin" in user["roles"]: # we are an admin for user in group["members"]: rendered_users.append({ "name": user["name"], "id": user["user_id"] }) break rendered_users = remove_dup_dict_in_list(rendered_users) if request.method == "GET": return render(request, "add_user.html", { "request": request, "users": rendered_users, "org": org, }) elif request.method == "POST": users = [i[2:] for i in request.POST.keys() if i.startswith("u_")] user_name_mappings = pickle.loads(bytes.fromhex(request.session["user_name_mapping"])) for user in users: try: username = user_name_mappings[user] except KeyError: username = "unknown" user_data = { "uid": user, "role": "trusted", "name": username, "number_messages": 0 } org_trusted_users.append(user_data) org.trusted_users = pickle.dumps(org_trusted_users).hex() org.save() return redirect(reverse('view_organization', args=[org.id])) def remove_user(request, org_id, user): org = get_org_by_id(org_id) org_trusted_users = from_pickle(org.trusted_users) for index, tuser in enumerate(org_trusted_users): print(index, tuser) if tuser["uid"] == user: org_trusted_users.pop(index) break org.trusted_users = to_pickle(org_trusted_users) org.save() return redirect(reverse('view_organization', args=[org.id]))