#!/usr/bin/env python

import json, sys, urllib, zipfile, tarfile, os, time

arduino_esp8266_manager_link = "http://arduino.esp8266.com/staging/package_esp8266com_index.json"

if not os.path.exists("downloads"):
  os.mkdir("downloads")

if not os.path.exists("tools"):
  os.mkdir("tools")

def defineHost():
  sys_platform = sys.platform
  sys_arch = 64 if sys.maxsize > 2**32 else 32

  if "linux" in sys_platform:
    if sys_arch > 32:
      host = "x86_64-pc-linux-gnu"
    else:
      host = "i686-pc-linux-gnu"
  elif "darwin" in sys_platform:
    if sys_arch > 32:
      host = "x86_64-apple-darwin"
    else:
      host = "i386-apple-darwin"
  else:
    host = None
  return host

def downloadTools(host):
  arduino_esp8266_json = json.loads(urllib.urlopen(arduino_esp8266_manager_link).read())
  download_path = "downloads/"
  tools_path = "tools/"

  platform = arduino_esp8266_json['packages'][0]['platforms'][0]
  xtensa = arduino_esp8266_json['packages'][0]['tools'][0]
  esptool = arduino_esp8266_json['packages'][0]['tools'][1]
  mkspiffs = arduino_esp8266_json['packages'][0]['tools'][3]

  urllib.urlretrieve(platform['url'], download_path + platform['archiveFileName'])
  with zipfile.ZipFile(download_path + platform['archiveFileName'], "r") as z:
      z.extractall(tools_path)
  os.rename(tools_path + platform['archiveFileName'][:-4], tools_path + "Arduino-Esp8266")
  print("Arduino ESP8266 Extension downloaded...")
  for item in xtensa['systems']:
    if host in item['host']:
      urllib.urlretrieve(item['url'], download_path + item['archiveFileName'])
      tfile = tarfile.open(download_path + item['archiveFileName'], 'r:gz')
      tfile.extractall(tools_path)
      print("Xtensa lx106 elf tools downloaded...")
      break

  for item in esptool['systems']:
    if host in item['host']:
      urllib.urlretrieve(item['url'], download_path + item['archiveFileName'])
      tfile = tarfile.open(download_path + item['archiveFileName'], 'r:gz')
      tf = tfile.getmembers()[1:]

      tfile.extractall(tools_path, tf)
      os.rename(tools_path + item['archiveFileName'][:-7], tools_path + "esptool")
      print("esptool downloaded...")
      break

  for item in mkspiffs['systems']:
    if host in item['host']:
      urllib.urlretrieve(item['url'], download_path + item['archiveFileName'])
      tfile = tarfile.open(download_path + item['archiveFileName'], 'r:gz')
      tf = tfile.getmembers()[1:]

      tfile.extractall(tools_path, tf)
      os.rename(tools_path + item['archiveFileName'][:-7], tools_path + "mkspiffs")
      print("mkspiffs downloaded...")
      break

def main():
  host = defineHost()
  print("System Host: " + host)
  if host:
    print("Downloading...")
    downloadTools(host)
    print("Done!")
  else:
    print("Not supported OS!")

if __name__ == '__main__':
  main()


import os
import cv2
from cv2 import aruco
import numpy as np
import time

calibration_aruco_id = 15
calib_marker_length = 15
head_aruco_id = 27
head_marker_length = 15

global_head_points = np.array([], dtype=np.int32).reshape(0,2)

bool_draw_marker = False

file_dir = 'D:\\FordOtosan\\distorsion_calibration_images\\'
video_capture = cv2.VideoCapture(0)
video_capture.set(3,640)
video_capture.set(4,480)
video_capture.set(5,20)

video_capture_2 = cv2.VideoCapture(2)
video_capture_2.set(3,640)
video_capture_2.set(4,480)
video_capture_2.set(5,20)
DIM = (640,480)
K=np.array([[433.1789201825628, 0.0, 336.0326551869997], [0.0, 430.52735997037956, 216.5706380556904], [0.0, 0.0, 1.0]])
D=np.array([[-0.05280848062554133], [-0.13174782579340452], [-0.028567480262252885], [0.060944836127339065]])

dim1 = DIM
dim2 = (640, 480)
dim3 = (640, 480)
balance=1.0

bool_start_1 = True
bool_start_2 = True

_width  = 15.0
_height = 15.0
_margin = 235.0

pts_dst_corner = np.array(
	[
		[[  		_margin, _margin 			]],
		[[ 			_margin, _height + _margin  ]],
		[[ _width + _margin, _height + _margin  ]],
		[[ _width + _margin, _margin 			]],
	]
)
pts_dst = np.array( pts_dst_corner, np.float32 )
scaled_K = K * dim1[0] / DIM[0]  # The values of K is to scale with image dimension.
scaled_K[2][2] = 1.0  # Except that K[2][2] is always 1.0
# This is how scaled_K, dim2 and balance are used to determine the final K used to un-distort image. OpenCV document failed to make this clear!
new_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(scaled_K, D, dim2, np.eye(3), balance=balance)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(scaled_K, D, np.eye(3), new_K, dim3, cv2.CV_16SC2)

aruco_dict = aruco.Dictionary_get( aruco.DICT_6X6_1000 )
markerLength = 15.0
arucoParams = aruco.DetectorParameters_create()

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, 1e-12)
counter = 1
file_dir = 'D:\\FordOtosan\\distorsion_calibration_images\\'
start_time = time.time()
avg_hz = 0
while True:
    ret, rgb = video_capture.read()
    ret_2, rgb_2 = video_capture_2.read()

    rgb = cv2.remap(rgb, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
    rgb_2 = cv2.remap(rgb_2, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)

    imgRemapped_gray = cv2.cvtColor(rgb, cv2.COLOR_BGR2GRAY)
    imgRemapped_gray_2 = cv2.cvtColor(rgb_2, cv2.COLOR_BGR2GRAY)

    corners, ids, rejectedImgPoints = aruco.detectMarkers(imgRemapped_gray, aruco_dict, parameters=arucoParams)
    corners_2, ids_2, rejectedImgPoints_2 = aruco.detectMarkers(imgRemapped_gray_2, aruco_dict, parameters=arucoParams)

    if ids is not None and bool_draw_marker == True:
        imgWithAruco = aruco.drawDetectedMarkers(rgb, corners, ids, (0,255,0))
    else:
        imgWithAruco = rgb
    if ids_2 is not None and bool_draw_marker == True:
        imgWithAruco_2 = aruco.drawDetectedMarkers(rgb_2, corners_2, ids_2, (0,255,0))
    else:
        imgWithAruco_2 = rgb_2

    if ids is None:
        calibration_index = []
        calibration_index = np.array(calibration_index)
        head_index = []
        head_index = np.array(head_index).astype(np.int32)
        #calibration_index.size
    else:
        ids_list = np.ndarray.tolist(ids)
        ids_array = np.array(ids_list)
        ids_array = ids_array.T
        ids_array = ids_array[0,:]
        calibration_index = np.where(ids_array == 15)
        head_index = np.where(ids_array == 27)
        calibration_index = calibration_index[0]
        head_index = head_index[0]

    if ids_2 is None:
        calibration_index_2 = []
        calibration_index_2 = np.array(calibration_index_2).astype(np.int32)
        head_index_2 = []
        head_index_2 = np.array(head_index_2).astype(np.int32)
        #calibration_index_2.size
    else:
        ids_list_2 = np.ndarray.tolist(ids_2)
        ids_array_2 = np.array(ids_list_2)
        ids_array_2 = ids_array_2.T
        ids_array_2 = ids_array_2[0,:]
        calibration_index_2 = np.where(ids_array_2 == 15)
        head_index_2 = np.where(ids_array_2 == 27)
        calibration_index_2 = calibration_index_2[0]
        head_index_2 = head_index_2[0]

    if calibration_index.size == 1: # if aruco marker detected
        calib_index = np.asscalar(calibration_index)
        calib_corner = corners[calib_index]
        pts_src = np.array( calib_corner, np.float32 )
        #pts_src = pts_src[0,:,:,:]
        pts_src = np.rollaxis(pts_src,1)
        if bool_start_1 == True:
            temp = pts_src
            bool_start_1 = False
        temp = temp*0.9 + pts_src*0.1
        h, status = cv2.findHomography( temp, pts_dst )
        out = cv2.warpPerspective( rgb, h, ( int( _width + _margin * 2 ), int( _height + _margin * 2 ) ) )
        gray = cv2.cvtColor(out, cv2.COLOR_BGR2GRAY)
        _,gray_thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)

        cv2.imshow("birds_view_1", out)
    else:   # if aruco marker is NOT detected
        imgWithAruco = rgb  # assign imRemapped_color to imgWithAruco directly

    if calibration_index_2.size == 1: # if aruco marker detected
        calib_index_2 = np.asscalar(calibration_index_2)
        #calib_id_2 = ids_2[calibration_index_2].reshape((1,1))
        calib_corner_2 = corners_2[calib_index_2]
        #rvec_2, tvec_2 , pose_2 = aruco.estimatePoseSingleMarkers(calib_corner_2, calib_marker_length, K, D) # For a single marker
        #rvec_2 = rvec_2[0,:,:]
        #tvec_2 = tvec_2[0,:,:]
        #imgWithAruco_2 = aruco.drawDetectedMarkers(rgb_2, calib_corner_2, calib_id_2, (0,255,0))
        #imgWithAruco = aruco.drawAxis(imgWithAruco, K, D, rvec, tvec, 20)    # axis length 100 can be changed according to your requirement
           # display
        pts_src_2 = np.array( calib_corner_2, np.float32 )
        #pts_src_2 = pts_src_2[0,:,:,:]
        pts_src_2 = np.rollaxis(pts_src_2,1)
        if bool_start_2 == True:
            temp_2 = pts_src_2
            bool_start_2 = False
        temp_2 = temp_2*0.9 + pts_src_2*0.1
        h_2, status_2 = cv2.findHomography( temp_2, pts_dst )
        out_2 = cv2.warpPerspective( rgb_2, h_2, ( int( _width + _margin * 2 ), int( _height + _margin * 2 ) ) )
        gray_2 = cv2.cvtColor(out_2, cv2.COLOR_BGR2GRAY)
        _,gray_thresh_2 = cv2.threshold(gray_2, 0, 255, cv2.THRESH_BINARY)
        cv2.imshow("birds_view_2", out_2)
    else:   # if aruco marker is NOT detected
        imgWithAruco = rgb  # assign imRemapped_color to imgWithAruco directly

    if (calibration_index.size == 1) and (calibration_index_2.size == 1):
        xor_mask = cv2.bitwise_xor(gray_thresh_2,gray_thresh)
        and_mask = cv2.bitwise_and(gray_thresh_2,gray_thresh)
        #and_mask = cv2.GaussianBlur(and_mask,(3, 3), 0)
        #xor_mask = cv2.GaussianBlur(xor_mask,(3, 3), 0)
        added_raw_image = cv2.addWeighted(out,0.5,out_2,0.5, gamma = 0.0)
        masked_1 = cv2.bitwise_and(out, out, mask=xor_mask)
        masked_2 = cv2.bitwise_and(out_2, out_2, mask=xor_mask)
        xor_img = cv2.add(masked_1,masked_2)
        and_img = cv2.bitwise_and(added_raw_image, added_raw_image, mask=and_mask)
        final_img = cv2.add(xor_img,and_img)

    if (head_index.size == 1) and (head_index_2.size == 1) and (calibration_index.size == 1) and (calibration_index_2.size == 1):
        head_scalar_index = np.asscalar(head_index)
        head_scalar_index_2 = np.asscalar(head_index_2)

        head_corner = corners[head_scalar_index]
        head_corner_2 = corners_2[head_scalar_index_2]

        pts_head = np.array( head_corner, np.float32 )
        pts_head_2 = np.array( head_corner_2, np.float32 )

        pts_head_mean = np.array([pts_head.mean(axis=1)])
        pts_head_mean_2 = np.array([pts_head_2.mean(axis=1)])

        global_head_mean_point = cv2.perspectiveTransform(pts_head_mean,h)
        global_head_mean_point_2 = cv2.perspectiveTransform(pts_head_mean_2,h_2)
        global_head_point = np.mean([global_head_mean_point,global_head_mean_point_2],axis = 0).astype(np.int32)
        global_head_point = global_head_point[0,:,:]
        global_head_points = np.vstack([global_head_points, global_head_point])

    elif (head_index.size == 1) and (head_index_2.size != 1) and (calibration_index.size == 1) and (calibration_index_2.size == 1):
        head_scalar_index = np.asscalar(head_index)
        head_corner = corners[head_scalar_index]
        pts_head = np.array( head_corner, np.float32 )
        pts_head_mean = np.array([pts_head.mean(axis=1)])
        global_head_point = cv2.perspectiveTransform(pts_head_mean,h)
        global_head_point = global_head_point[0,:,:].astype(np.int32)
        global_head_points = np.vstack([global_head_points, global_head_point])

    elif (head_index.size != 1) and (head_index_2.size == 1) and (calibration_index.size == 1) and (calibration_index_2.size == 1):
        head_scalar_index_2 = np.asscalar(head_index_2)
        head_corner_2 = corners_2[head_scalar_index_2]
        pts_head_2 = np.array( head_corner_2, np.float32 )
        pts_head_mean_2 = np.array([pts_head_2.mean(axis=1)])
        global_head_point = cv2.perspectiveTransform(pts_head_mean_2,h_2)
        global_head_point = global_head_point[0,:,:].astype(np.int32)
        global_head_points = np.vstack([global_head_points, global_head_point])

    if (calibration_index.size == 1) and (calibration_index_2.size == 1):
        final_img = cv2.polylines(final_img,[global_head_points],False,(0,255,0),2)
        cv2.imshow("stitched", final_img)

    cv2.imshow("orj", rgb)
    cv2.imshow("orj_2", rgb_2)
    elapsed_time = time.time() - start_time
    start_time =time.time()
    avg_hz = 0.8*avg_hz + 0.2/elapsed_time
    print(avg_hz)
    if cv2.waitKey(27) & 0xFF == ord('q') :
        break

video_capture.release()
video_capture_2.release()
cv2.destroyAllWindows()

driveME/Written but not used codes/aruco_multiple.py


import random
import time
from typing import Any, Dict, List, Optional

import pytest
import requests

from fides.api.graph.graph import DatasetGraph
from fides.api.models.privacy_request import PrivacyRequest
from fides.api.schemas.redis_cache import Identity
from fides.api.service.connectors import get_connector
from fides.api.task import graph_task
from fides.api.task.filter_results import filter_data_categories
from fides.api.task.graph_task import get_cached_data_for_erasures
from tests.ops.graph.graph_test_util import assert_rows_match
from tests.ops.test_helpers.saas_test_utils import poll_for_existence

@pytest.mark.skip(reason="Pending account resolution")
@pytest.mark.integration_saas
@pytest.mark.integration_sentry
def test_sentry_connection_test(sentry_connection_config) -> None:
    get_connector(sentry_connection_config).test_connection()

@pytest.mark.skip(reason="Pending account resolution")
@pytest.mark.integration_saas
@pytest.mark.integration_sentry
@pytest.mark.asyncio
async def test_sentry_access_request_task(
    db,
    policy,
    sentry_connection_config,
    sentry_dataset_config,
    sentry_identity_email,
) -> None:
    """Full access request based on the Sentry SaaS config"""

    privacy_request = PrivacyRequest(
        id=f"test_sentry_access_request_task_{random.randint(0, 1000)}"
    )
    identity = Identity(**{"email": sentry_identity_email})
    privacy_request.cache_identity(identity)

    dataset_name = sentry_connection_config.get_saas_config().fides_key
    merged_graph = sentry_dataset_config.get_graph()
    graph = DatasetGraph(merged_graph)

    v = await graph_task.run_access_request(
        privacy_request,
        policy,
        graph,
        [sentry_connection_config],
        {"email": sentry_identity_email},
        db,
    )

    assert_rows_match(
        v[f"{dataset_name}:organizations"],
        min_size=1,
        keys=[
            "id",
            "slug",
            "status",
            "name",
            "dateCreated",
            "isEarlyAdopter",
            "require2FA",
            "requireEmailVerification",
            "avatar",
            "features",
        ],
    )
    assert_rows_match(
        v[f"{dataset_name}:employees"],
        min_size=1,
        keys=[
            "id",
            "email",
            "name",
            "user",
            "role",
            "roleName",
            "pending",
            "expired",
            "flags",
            "dateCreated",
            "inviteStatus",
            "inviterName",
            "projects",
        ],
    )
    assert_rows_match(
        v[f"{dataset_name}:projects"],
        min_size=3,
        keys=[
            "id",
            "slug",
            "name",
            "isPublic",
            "isBookmarked",
            "color",
            "dateCreated",
            "firstEvent",
            "firstTransactionEvent",
            "hasSessions",
            "features",
            "status",
            "platform",
            "isInternal",
            "isMember",
            "hasAccess",
            "avatar",
            "organization",
        ],
    )

    assert_rows_match(
        v[f"{dataset_name}:user_feedback"],
        min_size=1,
        keys=[
            "id",
            "eventID",
            "name",
            "email",
            "comments",
            "dateCreated",
            "user",
            "event",
            "issue",
        ],
    )

    # Person returns empty dicts
    assert_rows_match(
        v[f"{dataset_name}:person"],
        min_size=1,
        keys=[
            "id",
            "hash",
            "tagValue",
            "identifier",
            "username",
            "email",
            "name",
            "ipAddress",
            "dateCreated",
            "avatarUrl",
        ],
    )

    target_categories = {"user"}
    filtered_results = filter_data_categories(
        v,
        target_categories,
        graph.data_category_field_mapping,
    )

    assert set(filtered_results.keys()) == {
        f"{dataset_name}:person",
        f"{dataset_name}:employees",
        f"{dataset_name}:user_feedback",
    }

    assert set(filtered_results[f"{dataset_name}:person"][0].keys()) == {
        "email",
        "name",
        "username",
    }
    assert (
        filtered_results[f"{dataset_name}:person"][0]["email"] == sentry_identity_email
    )

    assert set(filtered_results[f"{dataset_name}:employees"][0].keys()) == {
        "email",
        "user",
        "name",
    }
    assert (
        filtered_results[f"{dataset_name}:employees"][0]["email"]
        == sentry_identity_email
    )
    assert set(filtered_results[f"{dataset_name}:employees"][0]["user"].keys()) == {
        "email",
        "name",
        "avatarUrl",
        "username",
        "emails",
    }

    assert (
        filtered_results[f"{dataset_name}:employees"][0]["user"]["email"]
        == sentry_identity_email
    )
    assert filtered_results[f"{dataset_name}:employees"][0]["user"]["emails"] == [
        {"email": sentry_identity_email}
    ]

    assert set(filtered_results[f"{dataset_name}:user_feedback"][0].keys()) == {
        "email",
        "user",
        "comments",
        "name",
    }
    assert (
        filtered_results[f"{dataset_name}:user_feedback"][0]["email"]
        == sentry_identity_email
    )

    assert set(filtered_results[f"{dataset_name}:user_feedback"][0]["user"].keys()) == {
        "email",
        "name",
        "username",
    }
    assert (
        filtered_results[f"{dataset_name}:user_feedback"][0]["user"]["email"]
        == sentry_identity_email
    )

def _get_issues(
    project: Dict[str, Any],
    secrets: Dict[str, Any],
    headers: Dict[str, Any],
) -> Optional[List[Dict[str, Any]]]:
    response = requests.get(
        f"https://{secrets['domain']}/api/0/projects/{project['organization']['slug']}/{project['slug']}/issues/",
        headers=headers,
    )
    json = response.json()
    return json if response.ok and len(json) else None

def sentry_erasure_test_prep(sentry_connection_config, db):
    sentry_secrets = sentry_connection_config.secrets
    # Set the assignedTo field on a sentry issue to a given employee
    token = sentry_secrets.get("erasure_access_token")
    issue_url = sentry_secrets.get("issue_url")
    sentry_user_id = sentry_secrets.get("user_id_erasure")
    domain = sentry_secrets.get("domain")

    if not token or not issue_url or not sentry_user_id:
        # Exit early if these haven't been set locally
        return None, None, None

    headers = {"Authorization": f"Bearer {token}"}
    data = {"assignedTo": f"user:{sentry_user_id}"}
    response = requests.put(issue_url, json=data, headers=headers)
    assert response.ok
    assert response.json().get("assignedTo", {}).get("id") == sentry_user_id

    # Get projects
    response = requests.get(f"https://{domain}/api/0/projects/", headers=headers)
    assert response.ok
    project = response.json()[0]

    # Wait until issues returns data
    error_message = "The issues endpoint did not return the required data for testing during the time limit"
    poll_for_existence(
        _get_issues, (project, sentry_secrets, headers), error_message=error_message
    )

    # Temporarily sets the access token to one that works for erasures
    sentry_connection_config.secrets["access_token"] = sentry_secrets[
        "erasure_access_token"
    ]
    sentry_connection_config.save(db)

    # Grab a separate email for erasures
    erasure_email = sentry_secrets["erasure_identity_email"]
    return erasure_email, issue_url, headers

@pytest.mark.skip(reason="Pending account resolution")
@pytest.mark.integration_saas
@pytest.mark.integration_sentry
@pytest.mark.asyncio
async def test_sentry_erasure_request_task(
    db, policy, sentry_connection_config, sentry_dataset_config
) -> None:
    """
    Full erasure request based on the Sentry SaaS config.
    Also verifies issue data in access request.
    """

    erasure_email, issue_url, headers = sentry_erasure_test_prep(
        sentry_connection_config, db
    )

    privacy_request = PrivacyRequest(
        id=f"test_sentry_erasure_request_task_{random.randint(0, 1000)}"
    )
    identity = Identity(**{"email": erasure_email})
    privacy_request.cache_identity(identity)

    dataset_name = sentry_connection_config.get_saas_config().fides_key
    merged_graph = sentry_dataset_config.get_graph()
    graph = DatasetGraph(merged_graph)

    v = await graph_task.run_access_request(
        privacy_request,
        policy,
        graph,
        [sentry_connection_config],
        {"email": erasure_email},
        db,
    )

    assert_rows_match(
        v[f"{dataset_name}:organizations"],
        min_size=1,
        keys=[
            "id",
            "slug",
            "status",
            "name",
            "dateCreated",
            "isEarlyAdopter",
            "require2FA",
            "requireEmailVerification",
            "avatar",
            "features",
        ],
    )
    assert_rows_match(
        v[f"{dataset_name}:employees"],
        min_size=1,
        keys=[
            "id",
            "email",
            "name",
            "user",
            "role",
            "roleName",
            "pending",
            "expired",
            "flags",
            "dateCreated",
            "inviteStatus",
            "inviterName",
            "projects",
        ],
    )
    assert_rows_match(
        v[f"{dataset_name}:issues"],
        min_size=1,
        keys=[
            "id",
            "shareId",
            "shortId",
            "title",
            "culprit",
            "permalink",
            "logger",
            "level",
            "status",
            "statusDetails",
            "isPublic",
            "platform",
            "project",
            "type",
            "metadata",
            "numComments",
            "assignedTo",
            "isBookmarked",
            "isSubscribed",
            "subscriptionDetails",
            "hasSeen",
            "annotations",
            "isUnhandled",
            "count",
            "userCount",
            "firstSeen",
            "lastSeen",
            "stats",
        ],
    )

    assert v[f"{dataset_name}:issues"][0]["assignedTo"]["email"] == erasure_email

    x = await graph_task.run_erasure(
        privacy_request,
        policy,
        graph,
        [sentry_connection_config],
        {"email": erasure_email},
        get_cached_data_for_erasures(privacy_request.id),
        db,
    )

    # Masking request only issued to "issues" endpoint
    assert x == {
        "sentry_instance:projects": 0,
        "sentry_instance:person": 0,
        "sentry_instance:issues": 1,
        "sentry_instance:organizations": 0,
        "sentry_instance:user_feedback": 0,
        "sentry_instance:employees": 0,
    }

    # Verify the user has been assigned to None
    resp = requests.get(issue_url, headers=headers).json()
    assert resp["assignedTo"] is None


from plaza_metadata import fetch_plaza_metadata
from base_radio import BaseRadio, PeriodicFetchMetadataRadio, radio_holder
import signal

import ffmpeg
from pyrogram import Client, filters
import pyrogram
from pyrogram.types import Message
from pytgcalls import GroupCallFactory
from pyrogram.raw.functions.channels import GetFullChannel
from pyrogram.raw.functions.phone import EditGroupCallTitle

from config import ADMINS, API_HASH, API_ID, SESSION_NAME

CLIENT_TYPE = GroupCallFactory.MTPROTO_CLIENT_TYPE.PYROGRAM

pyro_client = Client(
    f"sessions/{SESSION_NAME}",
    api_hash=API_HASH,
    api_id=API_ID,
)

async def admin_filter(_, __, m: Message):
    return m.from_user.id in ADMINS

admin = filters.create(admin_filter)

@pyro_client.on_message(admin & filters.command('dc', prefixes='!'))
async def get_dc(client: Client, message: Message):
    await message.reply_text(f'dc {await client.storage.dc_id()}')

@pyro_client.on_message(admin & filters.command('ct', prefixes='!'))
async def change_name(client, message: Message):
    if len(message.command) < 3:
        await message.reply_text('!ct @group_username name')
        return

    peer = await client.resolve_peer(message.command[1].replace('@', ''))
    chat = await client.send(GetFullChannel(channel=peer))
    data = EditGroupCallTitle(call=chat.full_chat.call, title=message.command[2])
    await client.send(data)

@pyro_client.on_message(admin & filters.command('start', prefixes='!'))
async def start(client, message: Message):
    if len(message.command) < 3:
        await message.reply_text('!start @group_username https://link-to-stream/')
        return

    group = None
    try:
        group = await pyro_client.get_chat(message.command[1].replace('@', ''))
    except pyrogram.errors.exceptions.bad_request_400.UsernameInvalid:
        await message.reply_text(f'can''t resolve this username')

    stream_url = message.command[2].strip()

    group_radio = radio_holder.get_radio(group.id)
    if group_radio is None or not group_radio.is_streaming:
        if ('plaza.one' in stream_url):
            group_radio = PeriodicFetchMetadataRadio(
                stream_url,
                group.id,
                GroupCallFactory(
                    client,
                    path_to_log_file=''
                ),
                5,
                fetch_plaza_metadata,
            )
        else:
            group_radio = BaseRadio(
                stream_url,
                group.id,
                GroupCallFactory(
                    client,
                    path_to_log_file=''
                )
            )

        radio_holder.add_radio(group_radio)

    if (group_radio.is_streaming):
        await message.reply_text(f'Radio for {group.id} already playing')
        return

    await group_radio.start()

    await message.reply_text(f'Radio for {group.id} with {group_radio.url} is playing...')

@pyro_client.on_message(admin & filters.command('stop', prefixes='!'))
async def stop(_, message: Message):
    if len(message.command) < 2:
        await message.reply_text('!stop @group_username')
        return

    group = None
    try:
        group = await pyro_client.get_chat(message.command[1].replace('@', ''))
    except pyrogram.errors.exceptions.bad_request_400.UsernameInvalid:
        await message.reply_text(f'can''t resolve this username')

    group_radio = radio_holder.get_radio(group.id)
    if group_radio is None or not group_radio.is_streaming:
        await message.reply_text(f'Radio for {group.id} are not playing.')
        return

    await group_radio.stop()
    await message.reply_text(f'Radio for {group.id} stopped')

if __name__ == '__main__':
    pyro_client.run()