text: from datetime import datetime, timedelta
  from dateutil.parser import parse
  from dotenv import load_dotenv
  from gql import Client, gql
  from gql.transport.requests import RequestsHTTPTransport
  import os
  from result import Result
  
  PATH = ".." if "src" in os.getcwd() else "."
  
  load_dotenv() 
  
  GITHUB_API_TOKEN = os.environ.get("GITHUB_TOKEN")
  GITHUB_ENDPOINT = "https://api.github.com/graphql"
  GITHUB_HEADERS = {"Authorization": "token %s" % GITHUB_API_TOKEN}
  
  TIME_FRAME = datetime.now() - timedelta(days=7)
  
  client = Client(
      transport=RequestsHTTPTransport(
          url=GITHUB_ENDPOINT,
          headers={"Authorization": "token %s" % GITHUB_API_TOKEN}
      )
  )
  
  
  def t_stamp(iso_str):
      return parse(iso_str).replace(tzinfo=None)
  
  
  def decode_issues(response):
      issues = response["issues"]["nodes"]
      issues_opened, issues_closed = 0, 0
      for issue in issues:
          if t_stamp(issue["createdAt"]) > TIME_FRAME:
              issues_opened += 1
          if issue["closedAt"] is not None and t_stamp(issue["closedAt"]) > TIME_FRAME:
              issues_closed += 1
      return issues_opened, issues_closed
  
  
  def decode_prs(response):
      prs = response["pullRequests"]["nodes"]
      prs_opened, prs_closed, prs_merged = 0, 0, 0
      for pr in prs:
          if t_stamp(pr["createdAt"]) > TIME_FRAME:
              prs_opened += 1
          if pr["closedAt"] is not None and t_stamp(pr["closedAt"]) > TIME_FRAME:
              if pr["state"] == "CLOSED":
                  prs_closed += 1
              elif pr["state"] == "MERGED":
                  prs_merged += 1
      return prs_opened, prs_closed, prs_merged
  
  
  def decode_user_repos(user, login):
      additions, deletions, commit_count = 0, 0, 0
      try:  # analyze commits in own repos
          commit_nodes = user["repositories"]["nodes"]
          groups = []
          for node in commit_nodes:
              try:
                  r = node["defaultBranchRef"]["target"]["history"]["nodes"]
                  groups.append(r)
              except TypeError:
                  pass
          commits = [commit for group in groups for commit in group]
  
          for c in commits:
              try:
                  login_response = c["author"]["user"]["login"]
                  if login == login_response and t_stamp(c["committedDate"]) > TIME_FRAME:
                      additions += c.get("additions", 0)
                      deletions += c.get("deletions", 0)
                      commit_count += 1
              except (KeyError, TypeError):
                  pass
      except (KeyError, TypeError):
          pass
  
      return additions, deletions, commit_count
  
  
  def decode_user_contributions(user, login):
      additions, deletions, commit_count = 0, 0, 0
      try:  # analyze commits in repos contributed to
          commit_nodes = user["repositoriesContributedTo"]["nodes"]
          commit_edges = list(map(lambda x: x["refs"]["edges"], commit_nodes))
          for edge in commit_edges:
              for node in edge:
                  try:
                      data = node["node"]["target"]
                      login_response = data["author"]["user"]["login"]
                      if login == login_response and t_stamp(data["committedDate"]) > TIME_FRAME:
                          additions += data.get("additions", 0)
                          deletions += data.get("deletions", 0)
                          commit_count += 1
                  except (KeyError, TypeError):
                      pass
      except (KeyError, TypeError):
          return Result(error="Unable to parse github user query")
  
      return additions, deletions, commit_count
  
  
  def user_query(login) -> Result:
      try:
          with open("%s/queries/user.graphql" % PATH, "r") as f:  # Separate queries to avoid timeout
              query = f.read().replace("$login", "\"%s\"" % login)
              query = gql(query)
          response = client.execute(query)
          user = response.get("user")
  
          issues_opened, issues_closed = decode_issues(user)
          prs_opened, prs_closed, prs_merged = decode_prs(user)
          additions, deletions, commit_count = 0, 0, 0
  
          queries = [("user_repos", "r"), ("user_contributions", "c")]
          for f, q in queries:
              with open("%s/queries/%s.graphql" % (PATH, f), "r") as f:  # Separate queries to avoid timeout
                  query = f.read().replace("$login", "\"%s\"" % login)
                  query = gql(query)
              response = client.execute(query)
              user = response.get("user")
  
              adds, dels, coms = 0, 0, 0
              if q == "r":
                  adds, dels, coms = decode_user_repos(user, login)
              elif q == "c":
                  adds, dels, coms = decode_user_contributions(user, login)
              additions += adds
              deletions += dels
              commit_count += coms
  
          data = {
              "login": login,
              "commits": commit_count,
              "additions": additions,
              "deletions": deletions,
              "issues_opened": issues_opened,
              "issues_closed": issues_closed,
              "prs_opened": prs_opened,
              "prs_closed": prs_closed,
              "prs_merged": prs_merged
          }
          return Result(data=data)
      except KeyError:
          return Result(error="Response decoding failure")
  
  
  def decode_repo(response) -> Result:
      error = response.get("errors")
      if error is not None:
          return Result(error=error.get("message", "unknown error"))
  
      repo = response.get("repository")
      if repo is None:
          return Result(error="Parse failure")
  
      try:
          # analyze commits
          commit_nodes = repo["ref"]["target"]["history"]["edges"]
          commit_nodes = list(map(lambda x: x["node"], commit_nodes))
          additions, deletions, commit_count = 0, 0, 0
          for node in commit_nodes:
              if t_stamp(node["committedDate"]) > TIME_FRAME:
                  additions += node.get("additions", 0)
                  deletions += node.get("deletions", 0)
                  commit_count += 1
  
          issues_opened, issues_closed = decode_issues(repo)
          prs_opened, prs_closed, prs_merged = decode_prs(repo)
  
          # analyze watchers
          watchers = repo["watchers"]["nodes"]
          watchers_count = len(watchers)
  
          data = {
              "name": repo["name"],
              "owner": repo["owner"]["login"],
              "commits": commit_count,
              "additions": additions,
              "deletions": deletions,
              "issues_opened": issues_opened,
              "issues_closed": issues_closed,
              "prs_opened": prs_opened,
              "prs_closed": prs_closed,
              "prs_merged": prs_merged,
              "forks": repo.get("forks", 0),
              "watchers": watchers_count
          }
          return Result(data=data)
      except (KeyError, TypeError):
          return Result(error="Unable to parse github query")
      
  
  def repo_query(owner, repo_name) -> Result:
      with open("%s/queries/repo.graphql" % PATH, "r") as f:
          query = f.read()\
              .replace("$owner", "\"%s\"" % owner)\
              .replace("$name", "\"%s\"" % repo_name)
          query = gql(query)
  
      response = client.execute(query)
      try:
          parsed_response = decode_repo(response)
          return parsed_response
      except KeyError:
          return Result(error="Response decoding failure")
  