name: Close Unauthorized Issues

on:
  workflow_dispatch:
  issues:
    types: [opened]

jobs:
  close-unauthorized-issues:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      # XXX: This *could* be done in Bash by abusing GitHub's own tool to interact with its API
      # but that's too much of a hack, and we'll be adding a layer of abstraction. github-script
      # is a workflow that eases interaction with GitHub API in the workflow run context.
      - name: "Close 'unauthorized' issues"
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const ALLOWED_USERS = ['vaxerski', 'fufexan', 'NotAShelf'];
            const CLOSING_COMMENT = 'Users are no longer allowed to open issues themselves, please open a discussion instead.\n\nPlease see the [wiki](https://wiki.hyprland.org/Contributing-and-Debugging/Issue-Guidelines/) on why this is the case.\n\nWe are volunteers, and we need your cooperation to make the best software we can. Thank you for understanding! ❤️\n\n[Open a discussion here](https://github.com/hyprwm/Hyprland/discussions)';

            async function closeUnauthorizedIssue(issueNumber, userName) {
              if (ALLOWED_USERS.includes(userName)) {
                console.log(`Issue #${issueNumber} - Created by authorized user ${userName}`);
                return;
              }

              console.log(`Issue #${issueNumber} - Unauthorized, closing`);

              await github.rest.issues.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issueNumber,
                state: 'closed',
                state_reason: 'not_planned'
              });

              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issueNumber,
                body: CLOSING_COMMENT
              });
            }

            if (context.eventName === 'issues' && context.payload.action === 'opened') {
              // Direct access to the issue that triggered the workflow
              const issue = context.payload.issue;

              // Skip if this is a PR
              if (issue.pull_request) {
                console.log(`Issue #${issue.number} - Skipping, this is a pull request`);
                return;
              }

              // Process the single issue that triggered the workflow
              await closeUnauthorizedIssue(issue.number, issue.user.login);
            } else {
              // For manual runs, we need to handle pagination
              async function* fetchAllOpenIssues() {
                let page = 1;
                let hasNextPage = true;

                while (hasNextPage) {
                  const response = await github.rest.issues.listForRepo({
                    owner: context.repo.owner,
                    repo: context.repo.repo,
                    state: 'open',
                    per_page: 100,
                    page: page
                  });

                  if (response.data.length === 0) {
                    hasNextPage = false;
                  } else {
                    for (const issue of response.data) {
                      yield issue;
                    }
                    page++;
                  }
                }
              }

              // Process issues one by one
              for await (const issue of fetchAllOpenIssues()) {
                try {
                  // Skip pull requests
                  if (issue.pull_request) {
                    console.log(`Issue #${issue.number} - Skipping, this is a pull request`);
                    continue;
                  }

                  await closeUnauthorizedIssue(issue.number, issue.user.login);
                } catch (error) {
                  console.error(`Error processing issue #${issue.number}: ${error.message}`);
                }
              }
            }
