diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..9246dbfa --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "hour" diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 00000000..2f633b6d --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,26 @@ +name: Android CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew build diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml new file mode 100644 index 00000000..9766b45d --- /dev/null +++ b/.github/workflows/django.yml @@ -0,0 +1,30 @@ +name: Django CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: [3.7, 3.8, 3.9] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Run Tests + run: | + python manage.py test diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 00000000..6a2cd51e --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,98 @@ +name: Docker + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + schedule: + - cron: '18 3 * * *' + push: + branches: [ "main" ] + # Publish semver tags as releases. + tags: [ 'v*.*.*' ] + pull_request: + branches: [ "main" ] + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: ${{ github.repository }} + + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + # This is used to complete the identity challenge + # with sigstore/fulcio when running outside of PRs. + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Install the cosign tool except on PR + # https://github.com/sigstore/cosign-installer + - name: Install cosign + if: github.event_name != 'pull_request' + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0 + with: + cosign-release: 'v2.2.4' + + # Set up BuildKit Docker container builder to be able to build + # multi-platform images and export cache + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # Sign the resulting Docker image digest except on PRs. + # This will only write to the public Rekor transparency log when the Docker + # repository is public to avoid leaking data. If you would like to publish + # transparency data even for private images, pass --force to cosign below. + # https://github.com/sigstore/cosign + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable + TAGS: ${{ steps.meta.outputs.tags }} + DIGEST: ${{ steps.build-and-push.outputs.digest }} + # This step uses the identity token to provision an ephemeral certificate + # against the sigstore community Fulcio instance. + run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} diff --git a/.github/workflows/google.yml b/.github/workflows/google.yml new file mode 100644 index 00000000..0b5c7d12 --- /dev/null +++ b/.github/workflows/google.yml @@ -0,0 +1,116 @@ +# This workflow will build a docker container, publish it to Google Container +# Registry, and deploy it to GKE when there is a push to the "main" +# branch. +# +# To configure this workflow: +# +# 1. Enable the following Google Cloud APIs: +# +# - Artifact Registry (artifactregistry.googleapis.com) +# - Google Kubernetes Engine (container.googleapis.com) +# - IAM Credentials API (iamcredentials.googleapis.com) +# +# You can learn more about enabling APIs at +# https://support.google.com/googleapi/answer/6158841. +# +# 2. Ensure that your repository contains the necessary configuration for your +# Google Kubernetes Engine cluster, including deployment.yml, +# kustomization.yml, service.yml, etc. +# +# 3. Create and configure a Workload Identity Provider for GitHub: +# https://github.com/google-github-actions/auth#preferred-direct-workload-identity-federation. +# +# Depending on how you authenticate, you will need to grant an IAM principal +# permissions on Google Cloud: +# +# - Artifact Registry Administrator (roles/artifactregistry.admin) +# - Kubernetes Engine Developer (roles/container.developer) +# +# You can learn more about setting IAM permissions at +# https://cloud.google.com/iam/docs/manage-access-other-resources +# +# 5. Change the values in the "env" block to match your values. + +name: 'Build and Deploy to GKE' + +on: + push: + branches: + - '"main"' + +env: + PROJECT_ID: 'my-project' # TODO: update to your Google Cloud project ID + GAR_LOCATION: 'us-central1' # TODO: update to your region + GKE_CLUSTER: 'cluster-1' # TODO: update to your cluster name + GKE_ZONE: 'us-central1-c' # TODO: update to your cluster zone + DEPLOYMENT_NAME: 'gke-test' # TODO: update to your deployment name + REPOSITORY: 'samples' # TODO: update to your Artifact Registry docker repository name + IMAGE: 'static-site' + WORKLOAD_IDENTITY_PROVIDER: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider' # TODO: update to your workload identity provider + +jobs: + setup-build-publish-deploy: + name: 'Setup, Build, Publish, and Deploy' + runs-on: 'ubuntu-latest' + environment: 'production' + + permissions: + contents: 'read' + id-token: 'write' + + steps: + - name: 'Checkout' + uses: 'actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332' # actions/checkout@v4 + + # Configure Workload Identity Federation and generate an access token. + # + # See https://github.com/google-github-actions/auth for more options, + # including authenticating via a JSON credentials file. + - id: 'auth' + name: 'Authenticate to Google Cloud' + uses: 'google-github-actions/auth@f112390a2df9932162083945e46d439060d66ec2' # google-github-actions/auth@v2 + with: + workload_identity_provider: '${{ env.WORKLOAD_IDENTITY_PROVIDER }}' + + # Authenticate Docker to Google Cloud Artifact Registry + - name: 'Docker Auth' + uses: 'docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567' # docker/login-action@v3 + with: + username: 'oauth2accesstoken' + password: '${{ steps.auth.outputs.auth_token }}' + registry: '${{ env.GAR_LOCATION }}-docker.pkg.dev' + + # Get the GKE credentials so we can deploy to the cluster + - name: 'Set up GKE credentials' + uses: 'google-github-actions/get-gke-credentials@6051de21ad50fbb1767bc93c11357a49082ad116' # google-github-actions/get-gke-credentials@v2 + with: + cluster_name: '${{ env.GKE_CLUSTER }}' + location: '${{ env.GKE_ZONE }}' + + # Build the Docker image + - name: 'Build and push Docker container' + run: |- + DOCKER_TAG="${GAR_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMAGE}:${GITHUB_SHA}" + + docker build \ + --tag "${DOCKER_TAG}" \ + --build-arg GITHUB_SHA="${GITHUB_SHA}" \ + --build-arg GITHUB_REF="${GITHUB_REF}" \ + . + + docker push "${DOCKER_TAG}" + + # Set up kustomize + - name: 'Set up Kustomize' + run: |- + curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.4.3/kustomize_v5.4.3_linux_amd64.tar.gz + chmod u+x ./kustomize + + # Deploy the Docker image to the GKE cluster + - name: 'Deploy to GKE' + run: |- + # replacing the image name in the k8s template + ./kustomize edit set image LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:TAG=$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE:$GITHUB_SHA + ./kustomize build . | kubectl apply -f - + kubectl rollout status deployment/$DEPLOYMENT_NAME + kubectl get services -o wide diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml new file mode 100644 index 00000000..20d17dc3 --- /dev/null +++ b/.github/workflows/gradle-publish.yml @@ -0,0 +1,44 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle + +name: Gradle Package + +on: + release: + types: [created] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + + - name: Build with Gradle + run: ./gradlew build + + # The USERNAME and TOKEN need to correspond to the credentials environment variables used in + # the publishing section of your build.gradle + - name: Publish to GitHub Packages + run: ./gradlew publish + env: + USERNAME: ${{ github.actor }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml new file mode 100644 index 00000000..9827103f --- /dev/null +++ b/.github/workflows/ios.yml @@ -0,0 +1,44 @@ +name: iOS starter workflow + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + name: Build and Test default scheme using any available iPhone simulator + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set Default Scheme + run: | + scheme_list=$(xcodebuild -list -json | tr -d "\n") + default=$(echo $scheme_list | ruby -e "require 'json'; puts JSON.parse(STDIN.gets)['project']['targets'][0]") + echo $default | cat >default + echo Using default scheme: $default + - name: Build + env: + scheme: ${{ 'default' }} + platform: ${{ 'iOS Simulator' }} + run: | + # xcrun xctrace returns via stderr, not the expected stdout (see https://developer.apple.com/forums/thread/663959) + device=`xcrun xctrace list devices 2>&1 | grep -oE 'iPhone.*?[^\(]+' | head -1 | awk '{$1=$1;print}' | sed -e "s/ Simulator$//"` + if [ $scheme = default ]; then scheme=$(cat default); fi + if [ "`ls -A | grep -i \\.xcworkspace\$`" ]; then filetype_parameter="workspace" && file_to_build="`ls -A | grep -i \\.xcworkspace\$`"; else filetype_parameter="project" && file_to_build="`ls -A | grep -i \\.xcodeproj\$`"; fi + file_to_build=`echo $file_to_build | awk '{$1=$1;print}'` + xcodebuild build-for-testing -scheme "$scheme" -"$filetype_parameter" "$file_to_build" -destination "platform=$platform,name=$device" + - name: Test + env: + scheme: ${{ 'default' }} + platform: ${{ 'iOS Simulator' }} + run: | + # xcrun xctrace returns via stderr, not the expected stdout (see https://developer.apple.com/forums/thread/663959) + device=`xcrun xctrace list devices 2>&1 | grep -oE 'iPhone.*?[^\(]+' | head -1 | awk '{$1=$1;print}' | sed -e "s/ Simulator$//"` + if [ $scheme = default ]; then scheme=$(cat default); fi + if [ "`ls -A | grep -i \\.xcworkspace\$`" ]; then filetype_parameter="workspace" && file_to_build="`ls -A | grep -i \\.xcworkspace\$`"; else filetype_parameter="project" && file_to_build="`ls -A | grep -i \\.xcodeproj\$`"; fi + file_to_build=`echo $file_to_build | awk '{$1=$1;print}'` + xcodebuild test-without-building -scheme "$scheme" -"$filetype_parameter" "$file_to_build" -destination "platform=$platform,name=$device" diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml new file mode 100644 index 00000000..8789c17b --- /dev/null +++ b/.github/workflows/makefile.yml @@ -0,0 +1,27 @@ +name: Makefile CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: configure + run: ./configure + + - name: Install dependencies + run: make + + - name: Run check + run: make check + + - name: Run distcheck + run: make distcheck diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml new file mode 100644 index 00000000..11b2e355 --- /dev/null +++ b/.github/workflows/manual.yml @@ -0,0 +1,32 @@ +# This is a basic workflow that is manually triggered + +name: Manual workflow + +# Controls when the action will run. Workflow runs when manually triggered using the UI +# or API. +on: + workflow_dispatch: + # Inputs the workflow accepts. + inputs: + name: + # Friendly description to be shown in the UI instead of 'name' + description: 'Person to greet' + # Default value if no value is explicitly provided + default: 'World' + # Input has to be provided for the workflow to run + required: true + # The data type of the input + type: string + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "greet" + greet: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Runs a single command using the runners shell + - name: Send greeting + run: echo "Hello ${{ inputs.name }}" diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml new file mode 100644 index 00000000..64b848b6 --- /dev/null +++ b/.github/workflows/maven-publish.yml @@ -0,0 +1,34 @@ +# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path + +name: Maven Package + +on: + release: + types: [created] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Build with Maven + run: mvn -B package --file pom.xml + + - name: Publish to GitHub Packages Apache Maven + run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml + env: + GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/objective-c-xcode.yml b/.github/workflows/objective-c-xcode.yml new file mode 100644 index 00000000..add007bf --- /dev/null +++ b/.github/workflows/objective-c-xcode.yml @@ -0,0 +1,30 @@ +name: Xcode - Build and Analyze + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + name: Build and analyse default scheme using xcodebuild command + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set Default Scheme + run: | + scheme_list=$(xcodebuild -list -json | tr -d "\n") + default=$(echo $scheme_list | ruby -e "require 'json'; puts JSON.parse(STDIN.gets)['project']['targets'][0]") + echo $default | cat >default + echo Using default scheme: $default + - name: Build + env: + scheme: ${{ 'default' }} + run: | + if [ $scheme = default ]; then scheme=$(cat default); fi + if [ "`ls -A | grep -i \\.xcworkspace\$`" ]; then filetype_parameter="workspace" && file_to_build="`ls -A | grep -i \\.xcworkspace\$`"; else filetype_parameter="project" && file_to_build="`ls -A | grep -i \\.xcodeproj\$`"; fi + file_to_build=`echo $file_to_build | awk '{$1=$1;print}'` + xcodebuild clean build analyze -scheme "$scheme" -"$filetype_parameter" "$file_to_build" | xcpretty && exit ${PIPESTATUS[0]} diff --git a/.github/workflows/powershell.yml b/.github/workflows/powershell.yml new file mode 100644 index 00000000..7f566b3b --- /dev/null +++ b/.github/workflows/powershell.yml @@ -0,0 +1,49 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# +# https://github.com/microsoft/action-psscriptanalyzer +# For more information on PSScriptAnalyzer in general, see +# https://github.com/PowerShell/PSScriptAnalyzer + +name: PSScriptAnalyzer + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '21 21 * * 6' + +permissions: + contents: read + +jobs: + build: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + name: PSScriptAnalyzer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run PSScriptAnalyzer + uses: microsoft/psscriptanalyzer-action@6b2948b1944407914a58661c49941824d149734f + with: + # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options. + # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules. + path: .\ + recurse: true + # Include your own basic security rules. Removing this option will run all the rules + includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"' + output: results.sarif + + # Upload the SARIF file generated in the previous step + - name: Upload SARIF results file + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 00000000..c73e032c --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,23 @@ +name: Pylint + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10"] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pylint + - name: Analysing the code with pylint + run: | + pylint $(git ls-files '*.py') diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml new file mode 100644 index 00000000..1168bd9a --- /dev/null +++ b/.github/workflows/python-app.yml @@ -0,0 +1,39 @@ +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python application + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest + run: | + pytest diff --git a/.github/workflows/python-package-conda.yml b/.github/workflows/python-package-conda.yml new file mode 100644 index 00000000..f3586044 --- /dev/null +++ b/.github/workflows/python-package-conda.yml @@ -0,0 +1,34 @@ +name: Python Package using Conda + +on: [push] + +jobs: + build-linux: + runs-on: ubuntu-latest + strategy: + max-parallel: 5 + + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: '3.10' + - name: Add conda to system path + run: | + # $CONDA is an environment variable pointing to the root of the miniconda directory + echo $CONDA/bin >> $GITHUB_PATH + - name: Install dependencies + run: | + conda env update --file environment.yml --name base + - name: Lint with flake8 + run: | + conda install flake8 + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest + run: | + conda install pytest + pytest diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 00000000..82f8dbd9 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,70 @@ +# This workflow will upload a Python Package to PyPI when a release is created +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + release-build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - name: Build release distributions + run: | + # NOTE: put your own distribution build steps here. + python -m pip install build + python -m build + + - name: Upload distributions + uses: actions/upload-artifact@v4 + with: + name: release-dists + path: dist/ + + pypi-publish: + runs-on: ubuntu-latest + needs: + - release-build + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing + id-token: write + + # Dedicated environments with protections for publishing are strongly recommended. + # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules + environment: + name: pypi + # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status: + # url: https://pypi.org/p/YOURPROJECT + # + # ALTERNATIVE: if your GitHub Release name is the PyPI project version string + # ALTERNATIVE: exactly, uncomment the following line instead: + # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }} + + steps: + - name: Retrieve release distributions + uses: actions/download-artifact@v4 + with: + name: release-dists + path: dist/ + + - name: Publish release distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml new file mode 100644 index 00000000..21ae770f --- /dev/null +++ b/.github/workflows/swift.yml @@ -0,0 +1,22 @@ +# This workflow will build a Swift project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift + +name: Swift + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v4 + - name: Build + run: swift build -v + - name: Run tests + run: swift test -v diff --git a/.github/workflows/webpack.yml b/.github/workflows/webpack.yml new file mode 100644 index 00000000..9626ff6d --- /dev/null +++ b/.github/workflows/webpack.yml @@ -0,0 +1,28 @@ +name: NodeJS with Webpack + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x, 20.x, 22.x] + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Build + run: | + npm install + npx webpack diff --git a/Gilbert Algordo.vcf b/Gilbert Algordo.vcf new file mode 100644 index 00000000..43e30435 --- /dev/null +++ b/Gilbert Algordo.vcf @@ -0,0 +1,490 @@ +BEGIN:VCARD +VERSION:3.0 +PRODID:-//Apple Inc.//iPhone OS 16.7.10//EN +N:Algordo;Gilbert;;; +FN:Gilbert Algordo +ORG:NASA; +EMAIL;type=INTERNET;type=WORK;type=pref:algordogilbert@gmail.com +EMAIL;type=INTERNET;type=WORK:gilbert_algordo@yahoo.com +EMAIL;type=INTERNET:g32flavor@gmail.com +TEL;type=pref:09770355572 +item1.ADR;type=HOME;type=pref:;;B1 L1 Main Avenue cornerSennia\nCamella Homes Milan;San Pedro;Cuyab;4023;Philippines +item1.X-ABADR:ph +ADR;type=HOME:;;\nostini;San Pedro Laguna;blk.3 lot 86 Camella Milan Homes;4024;Philippines +ADR;type=HOME:;;ostini;San Pedro Laguna;blk.3 lot 86 Camella Milan Homes;4024;Philippines +item2.ADR;type=HOME:;;\nostini;San Pedro Laguna;blk.3 lot 86 Camella Milan Homes;4024;Philippines +item2.X-ABADR:ph +X-SOCIALPROFILE;type=facebook:http://www.facebook.com/gilbertalgordo +X-SOCIALPROFILE;type=twitter:http://twitter.com/gilbert_algordo +NOTE:This contact is read-only. To make changes\, tap the link above to edit in Outlook. +item3.URL;type=pref:ms-outlook://people/v3/0009002e00000000001d840311aa6611cd9bc800aa002fc45a0d001ca47b1ecd52ae4cb3928636f4b109d300009332ef2c0000?a=b87bf660c3b6b6197bf031a7de0e49cfc7c6348430218d6b1721828264f1942b&c=fb215f9e +item3.X-ABLabel:Outlook +item4.URL:ms-outlook://people/v3/0009002e00000000001d840311aa6611cd9bc800aa002fc45a0d001ca47b1ecd52ae4cb3928636f4b109d300009332f33e0000?a=b87bf660c3b6b6197bf031a7de0e49cfc7c6348430218d6b1721828264f1942b&c=320973a2 +item4.X-ABLabel:Outlook +item5.URL:https://discuss.ai.google.dev/u/gilbert_algordo/summary +item5.X-ABLabel:_$!!$_ +item6.URL:ms-outlook://people/v3/0009002e00000000001d840311aa6611cd9bc800aa002fc45a0d001ca47b1ecd52ae4cb3928636f4b109d30000170863300000?a=b87bf660c3b6b6197bf031a7de0e49cfc7c6348430218d6b1721828264f1942b&c=7d3a81d7 +item6.X-ABLabel:Outlook +item7.URL:https://g.dev/gilbert_algordo +item7.X-ABLabel:_$!!$_ +PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAASABIAAD/4QBMRXhpZgAATU0AKgAA + AAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABQKADAAQAAAABAA + ABQAAAAAD/wAARCAFAAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcI + CQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0f + AkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4 + eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2u + Hi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QA + tREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRCh + YkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE + hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5e + bn6Onq8vP09fb3+Pn6/9sAQwACAgICAgIDAgIDBQMDAwUGBQUFBQYIBgYGBgYICggICAgICAoK + CgoKCgoKDAwMDAwMDg4ODg4PDw8PDw8PDw8P/9sAQwECAgIEBAQHBAQHEAsJCxAQEBAQEBAQEB + AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ/90ABAAU/9oADAMBAAIR + AxEAPwD8AwecUnfntRijOcUAHHT1pRzzSdc57UDtQAdM+9ITzSEc8U9TkimgBeufWplGTUQ61O + mfzrspwAeuAc1YRTlT71EuMgVZjz6YxXVFHPKXUtRLjBrUt+1UI+laVsoyB611QueTXZoQjr+J + rdtADtz2NYqDnpW5aHO3nFdtPdHjYh6M7aDHnH8q9M8HbfPlJHSCT+VeXRtid8HkmvSvBjn7RO + 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 + uejBH//Z +END:VCARD diff --git a/advance_antispy.yaml b/advance_antispy.yaml new file mode 100644 index 00000000..e699c5d0 --- /dev/null +++ b/advance_antispy.yaml @@ -0,0 +1,137 @@ +import React, { useState, useEffect } from 'react'; + +const AdvanceAntispy = () => { + const [isClipboardAccessed, setIsClipboardAccessed] = useState(false); + const [isCameraAccessed, setIsCameraAccessed] = useState(false); + const [isMicrophoneAccessed, setIsMicrophoneAccessed] = useState(false); + const [isLocationAccessed, setIsLocationAccessed] = useState(false); + const [isScreenShared, setIsScreenShared] = useState(false); + const [isIdle, setIsIdle] = useState(true); + const [idleTimer, setIdleTimer] = useState(null); + + const IDLE_TIMEOUT = 60000; // 1 minute of inactivity + + useEffect(() => { + const handleVisibilityChange = () => { + if (document.hidden) { + console.log('Tab Hidden'); + // Additional logic when the tab is hidden (e.g., clear sensitive data) + } else { + console.log('Tab Visible'); + // Additional logic when the tab is visible + } + }; + + document.addEventListener('visibilitychange', handleVisibilityChange); + + return () => { + document.removeEventListener('visibilitychange', handleVisibilityChange); + }; + }, []); + + useEffect(() => { + const checkClipboardAccess = async () => { + try { + await navigator.clipboard.readText(); + setIsClipboardAccessed(true); + } catch (error) { + setIsClipboardAccessed(false); + } + }; + + const checkCameraAccess = async () => { + try { + const stream = await navigator.mediaDevices.getUserMedia({ video: true }); + stream.getTracks().forEach((track) => track.stop()); + setIsCameraAccessed(true); + } catch (error) { + setIsCameraAccessed(false); + } + }; + + const checkMicrophoneAccess = async () => { + try { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + stream.getTracks().forEach((track) => track.stop()); + setIsMicrophoneAccessed(true); + } catch (error) { + setIsMicrophoneAccessed(false); + } + }; + + const checkLocationAccess = async () => { + if ('geolocation' in navigator) { + try { + await new Promise((resolve, reject) => { + navigator.geolocation.getCurrentPosition(resolve, reject, { timeout: 5000 }); + }); + setIsLocationAccessed(true); + } catch (error) { + setIsLocationAccessed(false); + } + } else { + setIsLocationAccessed(false); + } + }; + + const checkScreenSharing = async () => { + try { + await navigator.mediaDevices.getDisplayMedia({ video: true }); + setIsScreenShared(true); + } catch (error) { + setIsScreenShared(false); + } + }; + + checkClipboardAccess(); + checkCameraAccess(); + checkMicrophoneAccess(); + checkLocationAccess(); + checkScreenSharing(); + }, []); + + useEffect(() => { + const resetIdleTimer = () => { + setIsIdle(false); + clearTimeout(idleTimer); + setIdleTimer(setTimeout(() => setIsIdle(true), IDLE_TIMEOUT)); + }; + + const handleUserActivity = () => { + resetIdleTimer(); + }; + + window.addEventListener('mousemove', handleUserActivity); + window.addEventListener('keydown', handleUserActivity); + window.addEventListener('click', handleUserActivity); + window.addEventListener('touchstart', handleUserActivity); + + resetIdleTimer(); // Initial call to set up the timer + + return () => { + window.removeEventListener('mousemove', handleUserActivity); + window.removeEventListener('keydown', handleUserActivity); + window.removeEventListener('click', handleUserActivity); + window.removeEventListener('touchstart', handleUserActivity); + clearTimeout(idleTimer); + }; + }, [idleTimer]); + + return ( +
+

Advanced Anti-Spy Features

+

Clipboard Accessed: {isClipboardAccessed ? 'Yes' : 'No'}

+

Camera Accessed: {isCameraAccessed ? 'Yes' : 'No'}

+

Microphone Accessed: {isMicrophoneAccessed ? 'Yes' : 'No'}

+

Location Accessed: {isLocationAccessed ? 'Yes' : 'No'}

+

Screen Shared: {isScreenShared ? 'Yes' : 'No'}

+

User Idle: {isIdle ? 'Yes' : 'No'}

+ + {isIdle &&

User is idle. Consider locking sensitive data.

} + + {/* Add more advanced detection logic here, like network monitoring, etc. */} +
+ ); +}; + +export default AdvanceAntispy; diff --git a/ai b/ai new file mode 100644 index 00000000..fee65039 --- /dev/null +++ b/ai @@ -0,0 +1,28 @@ +{ + "textPrompt": { + }, + "runSettings": { + "temperature": 1.0, + "model": "models/gemini-1.5-pro-latest", + "candidateCount": 1, + "topP": 0.95, + "topK": 64, + "maxOutputTokens": 8192, + "safetySettings": [{ + "category": "HARM_CATEGORY_HARASSMENT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, { + "category": "HARM_CATEGORY_HATE_SPEECH", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }], + "responseMimeType": "application/json" + }, + "testExamples": [{ + }] +} \ No newline at end of file diff --git a/cooling_system b/cooling_system new file mode 100644 index 00000000..926c8680 --- /dev/null +++ b/cooling_system @@ -0,0 +1,95 @@ +import React, { useState, useEffect } from 'react'; + +function CoolingSystem() { + const [temperature, setTemperature] = useState(25); // Initial temperature + const [coolingEnabled, setCoolingEnabled] = useState(false); + const [targetTemperature, setTargetTemperature] = useState(20); + const [fanSpeed, setFanSpeed] = useState(0); // 0: off, 1: low, 2: medium, 3: high + + useEffect(() => { + let interval; + + if (coolingEnabled) { + interval = setInterval(() => { + setTemperature((prevTemp) => { + if (prevTemp > targetTemperature) { + const newTemp = prevTemp - 0.5; // Simulate cooling + return newTemp < targetTemperature ? targetTemperature : newTemp; + } else if (prevTemp < targetTemperature) { + const newTemp = prevTemp + 0.2; // Simulate natural heating + return newTemp > targetTemperature ? targetTemperature : newTemp; + } else { + return prevTemp; + } + }); + }, 1000); // Update every second + } else { + interval = setInterval(() => { + setTemperature((prevTemp) => prevTemp + 0.1); // Simulate natural heating + }, 1000) + } + + return () => clearInterval(interval); // Cleanup interval on unmount or coolingEnabled change + }, [coolingEnabled, targetTemperature]); + + useEffect(() => { + if (coolingEnabled && temperature > targetTemperature) { + if (temperature - targetTemperature > 5) { + setFanSpeed(3); // High fan speed + } else if (temperature - targetTemperature > 3) { + setFanSpeed(2); // Medium fan speed + } else { + setFanSpeed(1); // Low fan speed + } + } else { + setFanSpeed(0); // Turn off fan + } + }, [temperature, targetTemperature, coolingEnabled]); + + const handleCoolingToggle = () => { + setCoolingEnabled(!coolingEnabled); + }; + + const handleTargetTemperatureChange = (event) => { + const newTarget = parseInt(event.target.value); + setTargetTemperature(newTarget); + }; + + const fanSpeedLabels = { + 0: 'Off', + 1: 'Low', + 2: 'Medium', + 3: 'High', + }; + + return ( +
+

Cooling System

+

Current Temperature: {temperature.toFixed(1)}°C

+ +
+ +

Cooling: {coolingEnabled ? 'Enabled' : 'Disabled'}

+

Fan Speed: {fanSpeedLabels[fanSpeed]}

+
+
+
+
+

Temperature Visual

+
+
+ ); +} + +export default CoolingSystem; diff --git a/googlebot.json b/googlebot.json new file mode 100644 index 00000000..af773254 --- /dev/null +++ b/googlebot.json @@ -0,0 +1,752 @@ +{ + "creationTime": "2025-02-25T15:46:15.000000", + "prefixes": [ + { + "ipv6Prefix": "2001:4860:4801:10::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:11::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:12::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:13::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:14::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:15::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:16::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:17::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:18::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:19::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:1a::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:1b::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:1c::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:1d::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:1e::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:1f::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:20::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:21::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:22::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:23::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:24::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:25::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:26::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:27::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:28::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:29::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:2::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:2a::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:2b::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:2c::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:2d::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:2e::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:2f::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:31::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:32::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:33::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:34::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:35::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:36::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:37::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:38::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:39::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:3a::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:3b::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:3c::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:3d::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:3e::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:40::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:41::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:42::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:43::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:44::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:45::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:46::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:47::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:48::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:49::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:4a::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:4b::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:50::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:51::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:53::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:54::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:55::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:60::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:61::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:62::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:63::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:64::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:65::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:66::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:67::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:68::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:69::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:6a::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:6b::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:6c::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:6d::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:6e::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:6f::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:70::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:71::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:72::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:73::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:74::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:75::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:76::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:77::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:78::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:79::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:80::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:81::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:82::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:83::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:84::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:85::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:86::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:87::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:88::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:90::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:91::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:92::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:93::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:94::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:95::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:a0::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:a1::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:a2::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:a3::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:a4::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:a5::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:c::/64" + }, + { + "ipv6Prefix": "2001:4860:4801:f::/64" + }, + { + "ipv4Prefix": "192.178.5.0/27" + }, + { + "ipv4Prefix": "192.178.6.0/27" + }, + { + "ipv4Prefix": "192.178.6.128/27" + }, + { + "ipv4Prefix": "192.178.6.160/27" + }, + { + "ipv4Prefix": "192.178.6.192/27" + }, + { + "ipv4Prefix": "192.178.6.32/27" + }, + { + "ipv4Prefix": "192.178.6.64/27" + }, + { + "ipv4Prefix": "192.178.6.96/27" + }, + { + "ipv4Prefix": "34.100.182.96/28" + }, + { + "ipv4Prefix": "34.101.50.144/28" + }, + { + "ipv4Prefix": "34.118.254.0/28" + }, + { + "ipv4Prefix": "34.118.66.0/28" + }, + { + "ipv4Prefix": "34.126.178.96/28" + }, + { + "ipv4Prefix": "34.146.150.144/28" + }, + { + "ipv4Prefix": "34.147.110.144/28" + }, + { + "ipv4Prefix": "34.151.74.144/28" + }, + { + "ipv4Prefix": "34.152.50.64/28" + }, + { + "ipv4Prefix": "34.154.114.144/28" + }, + { + "ipv4Prefix": "34.155.98.32/28" + }, + { + "ipv4Prefix": "34.165.18.176/28" + }, + { + "ipv4Prefix": "34.175.160.64/28" + }, + { + "ipv4Prefix": "34.176.130.16/28" + }, + { + "ipv4Prefix": "34.22.85.0/27" + }, + { + "ipv4Prefix": "34.64.82.64/28" + }, + { + "ipv4Prefix": "34.65.242.112/28" + }, + { + "ipv4Prefix": "34.80.50.80/28" + }, + { + "ipv4Prefix": "34.88.194.0/28" + }, + { + "ipv4Prefix": "34.89.10.80/28" + }, + { + "ipv4Prefix": "34.89.198.80/28" + }, + { + "ipv4Prefix": "34.96.162.48/28" + }, + { + "ipv4Prefix": "35.247.243.240/28" + }, + { + "ipv4Prefix": "66.249.64.0/27" + }, + { + "ipv4Prefix": "66.249.64.128/27" + }, + { + "ipv4Prefix": "66.249.64.160/27" + }, + { + "ipv4Prefix": "66.249.64.224/27" + }, + { + "ipv4Prefix": "66.249.64.32/27" + }, + { + "ipv4Prefix": "66.249.64.64/27" + }, + { + "ipv4Prefix": "66.249.64.96/27" + }, + { + "ipv4Prefix": "66.249.65.0/27" + }, + { + "ipv4Prefix": "66.249.65.128/27" + }, + { + "ipv4Prefix": "66.249.65.160/27" + }, + { + "ipv4Prefix": "66.249.65.192/27" + }, + { + "ipv4Prefix": "66.249.65.224/27" + }, + { + "ipv4Prefix": "66.249.65.32/27" + }, + { + "ipv4Prefix": "66.249.65.64/27" + }, + { + "ipv4Prefix": "66.249.65.96/27" + }, + { + "ipv4Prefix": "66.249.66.0/27" + }, + { + "ipv4Prefix": "66.249.66.160/27" + }, + { + "ipv4Prefix": "66.249.66.192/27" + }, + { + "ipv4Prefix": "66.249.66.32/27" + }, + { + "ipv4Prefix": "66.249.66.64/27" + }, + { + "ipv4Prefix": "66.249.66.96/27" + }, + { + "ipv4Prefix": "66.249.68.0/27" + }, + { + "ipv4Prefix": "66.249.68.32/27" + }, + { + "ipv4Prefix": "66.249.68.64/27" + }, + { + "ipv4Prefix": "66.249.68.96/27" + }, + { + "ipv4Prefix": "66.249.69.0/27" + }, + { + "ipv4Prefix": "66.249.69.128/27" + }, + { + "ipv4Prefix": "66.249.69.160/27" + }, + { + "ipv4Prefix": "66.249.69.192/27" + }, + { + "ipv4Prefix": "66.249.69.224/27" + }, + { + "ipv4Prefix": "66.249.69.32/27" + }, + { + "ipv4Prefix": "66.249.69.64/27" + }, + { + "ipv4Prefix": "66.249.69.96/27" + }, + { + "ipv4Prefix": "66.249.70.0/27" + }, + { + "ipv4Prefix": "66.249.70.128/27" + }, + { + "ipv4Prefix": "66.249.70.160/27" + }, + { + "ipv4Prefix": "66.249.70.192/27" + }, + { + "ipv4Prefix": "66.249.70.224/27" + }, + { + "ipv4Prefix": "66.249.70.32/27" + }, + { + "ipv4Prefix": "66.249.70.64/27" + }, + { + "ipv4Prefix": "66.249.70.96/27" + }, + { + "ipv4Prefix": "66.249.71.0/27" + }, + { + "ipv4Prefix": "66.249.71.128/27" + }, + { + "ipv4Prefix": "66.249.71.160/27" + }, + { + "ipv4Prefix": "66.249.71.192/27" + }, + { + "ipv4Prefix": "66.249.71.224/27" + }, + { + "ipv4Prefix": "66.249.71.32/27" + }, + { + "ipv4Prefix": "66.249.71.64/27" + }, + { + "ipv4Prefix": "66.249.71.96/27" + }, + { + "ipv4Prefix": "66.249.72.0/27" + }, + { + "ipv4Prefix": "66.249.72.128/27" + }, + { + "ipv4Prefix": "66.249.72.160/27" + }, + { + "ipv4Prefix": "66.249.72.192/27" + }, + { + "ipv4Prefix": "66.249.72.224/27" + }, + { + "ipv4Prefix": "66.249.72.32/27" + }, + { + "ipv4Prefix": "66.249.72.64/27" + }, + { + "ipv4Prefix": "66.249.72.96/27" + }, + { + "ipv4Prefix": "66.249.73.0/27" + }, + { + "ipv4Prefix": "66.249.73.128/27" + }, + { + "ipv4Prefix": "66.249.73.160/27" + }, + { + "ipv4Prefix": "66.249.73.192/27" + }, + { + "ipv4Prefix": "66.249.73.224/27" + }, + { + "ipv4Prefix": "66.249.73.32/27" + }, + { + "ipv4Prefix": "66.249.73.64/27" + }, + { + "ipv4Prefix": "66.249.73.96/27" + }, + { + "ipv4Prefix": "66.249.74.0/27" + }, + { + "ipv4Prefix": "66.249.74.128/27" + }, + { + "ipv4Prefix": "66.249.74.160/27" + }, + { + "ipv4Prefix": "66.249.74.32/27" + }, + { + "ipv4Prefix": "66.249.74.64/27" + }, + { + "ipv4Prefix": "66.249.74.96/27" + }, + { + "ipv4Prefix": "66.249.75.0/27" + }, + { + "ipv4Prefix": "66.249.75.128/27" + }, + { + "ipv4Prefix": "66.249.75.160/27" + }, + { + "ipv4Prefix": "66.249.75.192/27" + }, + { + "ipv4Prefix": "66.249.75.224/27" + }, + { + "ipv4Prefix": "66.249.75.32/27" + }, + { + "ipv4Prefix": "66.249.75.64/27" + }, + { + "ipv4Prefix": "66.249.75.96/27" + }, + { + "ipv4Prefix": "66.249.76.0/27" + }, + { + "ipv4Prefix": "66.249.76.128/27" + }, + { + "ipv4Prefix": "66.249.76.160/27" + }, + { + "ipv4Prefix": "66.249.76.192/27" + }, + { + "ipv4Prefix": "66.249.76.224/27" + }, + { + "ipv4Prefix": "66.249.76.32/27" + }, + { + "ipv4Prefix": "66.249.76.64/27" + }, + { + "ipv4Prefix": "66.249.76.96/27" + }, + { + "ipv4Prefix": "66.249.77.0/27" + }, + { + "ipv4Prefix": "66.249.77.128/27" + }, + { + "ipv4Prefix": "66.249.77.160/27" + }, + { + "ipv4Prefix": "66.249.77.192/27" + }, + { + "ipv4Prefix": "66.249.77.224/27" + }, + { + "ipv4Prefix": "66.249.77.32/27" + }, + { + "ipv4Prefix": "66.249.77.64/27" + }, + { + "ipv4Prefix": "66.249.77.96/27" + }, + { + "ipv4Prefix": "66.249.78.0/27" + }, + { + "ipv4Prefix": "66.249.78.32/27" + }, + { + "ipv4Prefix": "66.249.79.0/27" + }, + { + "ipv4Prefix": "66.249.79.128/27" + }, + { + "ipv4Prefix": "66.249.79.160/27" + }, + { + "ipv4Prefix": "66.249.79.192/27" + }, + { + "ipv4Prefix": "66.249.79.224/27" + }, + { + "ipv4Prefix": "66.249.79.32/27" + }, + { + "ipv4Prefix": "66.249.79.64/27" + }, + { + "ipv4Prefix": "66.249.79.96/27" + } + ] +} \ No newline at end of file diff --git a/ios_updater b/ios_updater new file mode 100644 index 00000000..c42527e4 --- /dev/null +++ b/ios_updater @@ -0,0 +1,29 @@ +import UIKit + +class UpdateManager { + let updateURL = URL(string: "https://example.com/path/to/update.json")! + + func checkForUpdate(completion: @escaping (Bool, String?) -> Void) { + let task = URLSession.shared.dataTask(with: updateURL) { data, response, error in + guard let data = data, error == nil else { + completion(false, nil) + return + } + + do { + if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { + let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String + if let latestVersion = json["version"] as? String, latestVersion != currentVersion { + let releaseNotes = json["releaseNotes"] as? String + completion(true, releaseNotes) + } else { + completion(false, nil) + } + } + } catch { + completion(false, nil) + } + } + task.resume() + } +} diff --git a/ios_updater_new b/ios_updater_new new file mode 100644 index 00000000..104969e0 --- /dev/null +++ b/ios_updater_new @@ -0,0 +1,39 @@ +import UIKit + +class UpdateManager { + private let updateURL = URL(string: "https://example.com/path/to/update.json")! // Replace with your URL + + func checkForUpdate(completion: @escaping (Bool, String?, String?) -> Void) { + let task = URLSession.shared.dataTask(with: updateURL) { data, _, error in + guard let data = data, error == nil else { + print("Error fetching update info: \(error?.localizedDescription ?? "Unknown error")") + completion(false, nil, nil) + return + } + + do { + if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], + let latestVersion = json["version"] as? String { + + let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String + + if let currentVersion = currentVersion, self.isNewVersionAvailable(currentVersion, latestVersion) { + let releaseNotes = json["releaseNotes"] as? String + let downloadURL = json["downloadURL"] as? String // URL to App Store or direct download + completion(true, releaseNotes, downloadURL) + } else { + completion(false, nil, nil) + } + } + } catch { + print("JSON Parsing error: \(error)") + completion(false, nil, nil) + } + } + task.resume() + } + + private func isNewVersionAvailable(_ currentVersion: String, _ latestVersion: String) -> Bool { + return currentVersion.compare(latestVersion, options: .numeric) == .orderedAscending + } +} diff --git a/ios_updater_prompt b/ios_updater_prompt new file mode 100644 index 00000000..10563585 --- /dev/null +++ b/ios_updater_prompt @@ -0,0 +1,36 @@ +import UIKit + +class ViewController: UIViewController { + let updateManager = UpdateManager() + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + checkForUpdates() + } + + private func checkForUpdates() { + updateManager.checkForUpdate { [weak self] isUpdateAvailable, releaseNotes, downloadURL in + guard let self = self, isUpdateAvailable, let downloadURL = downloadURL else { return } + + DispatchQueue.main.async { + self.showUpdateAlert(releaseNotes: releaseNotes, updateURL: downloadURL) + } + } + } + + private func showUpdateAlert(releaseNotes: String?, updateURL: String) { + let alert = UIAlertController(title: "Update Available", + message: releaseNotes ?? "A new version is available.", + preferredStyle: .alert) + + alert.addAction(UIAlertAction(title: "Update", style: .default, handler: { _ in + if let url = URL(string: updateURL) { + UIApplication.shared.open(url) + } + })) + + alert.addAction(UIAlertAction(title: "Later", style: .cancel, handler: nil)) + + present(alert, animated: true) + } +} diff --git a/ios_updater_server.json b/ios_updater_server.json new file mode 100644 index 00000000..f37d95c4 --- /dev/null +++ b/ios_updater_server.json @@ -0,0 +1,5 @@ +{ + "version": "2.0.0", + "releaseNotes": "New features and bug fixes.", + "downloadURL": "https://apps.apple.com/app/id123456789" // Replace with your App Store link +}