forked from natto1784/singh3
		
	Compare commits
	
		
			25 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 60adc1e937 | |||
| af80a94cfb | |||
| cdf5c2bce6 | |||
| 25735e3581 | |||
| a3919853b0 | |||
| a4e7c64193 | |||
| 0453caee43 | |||
| 5779f54f2d | |||
| 1d63fc050c | |||
| 05dc40863e | |||
| c04ec75f3e | |||
| 5d24893af6 | |||
| cee2e47b6c | |||
| cffeff4e27 | |||
| d20326a846 | |||
| a7a15dc3b1 | |||
| 18b19f0695 | |||
| f59a2c1b7f | |||
| 9a01af14f7 | |||
| 8e732b34ca | |||
| 5c911042be | |||
| 8177787376 | |||
| 44aba55f5e | |||
| b43472227a | |||
| 5f8ceb94b2 | 
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					Cargo.nix linguist-generated
 | 
				
			||||||
							
								
								
									
										21
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,21 +0,0 @@
 | 
				
			|||||||
name: main
 | 
					 | 
				
			||||||
on:
 | 
					 | 
				
			||||||
  push:
 | 
					 | 
				
			||||||
  pull_request:
 | 
					 | 
				
			||||||
  workflow_dispatch:
 | 
					 | 
				
			||||||
jobs:
 | 
					 | 
				
			||||||
  packages:
 | 
					 | 
				
			||||||
    name: test packages
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					 | 
				
			||||||
    steps:
 | 
					 | 
				
			||||||
      - uses: actions/checkout@v2.3.4
 | 
					 | 
				
			||||||
      - uses: cachix/install-nix-action@v13
 | 
					 | 
				
			||||||
        with:
 | 
					 | 
				
			||||||
          install_url: https://github.com/numtide/nix-flakes-installer/releases/download/nix-2.4pre20210429_d15a196/install
 | 
					 | 
				
			||||||
          extra_nix_config: |
 | 
					 | 
				
			||||||
            experimental-features = nix-command flakes
 | 
					 | 
				
			||||||
      - uses: cachix/cachix-action@v10
 | 
					 | 
				
			||||||
        with:
 | 
					 | 
				
			||||||
          name: natto1784
 | 
					 | 
				
			||||||
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
 | 
					 | 
				
			||||||
      - run: nix build
 | 
					 | 
				
			||||||
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,7 @@
 | 
				
			|||||||
target/
 | 
					target/
 | 
				
			||||||
result
 | 
					result
 | 
				
			||||||
 | 
					\#*\#
 | 
				
			||||||
 | 
					.\#*
 | 
				
			||||||
 | 
					.*~*~
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					result-bin
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										714
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										714
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,19 +1,22 @@
 | 
				
			|||||||
 | 
					cargo-features = ["edition2021"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "singh3"
 | 
					name = "singh3"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
authors = [ "Amneesh Singh <natto@weirdnatto.in>" ]
 | 
					authors = [ "Amneesh Singh <natto@weirdnatto.in>" ]
 | 
				
			||||||
edition = "2018"
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
tracing = "*"
 | 
					tracing = "*"
 | 
				
			||||||
regex = "*"
 | 
					regex = "1"
 | 
				
			||||||
tokio-postgres = "*"
 | 
					tokio-postgres = "*"
 | 
				
			||||||
rand = "*"
 | 
					rand = "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies.serenity]
 | 
					[dependencies.serenity]
 | 
				
			||||||
version = "0.10.*"
 | 
					version = "0.10.10"
 | 
				
			||||||
features = ["cache", "framework", "standard_framework", "rustls_backend", "unstable_discord_api", "collector"]
 | 
					features = ["cache", "framework", "standard_framework", "rustls_backend", "unstable_discord_api", "collector"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies.tokio]
 | 
					[dependencies.tokio]
 | 
				
			||||||
version = "1.0"
 | 
					version = "1.0"
 | 
				
			||||||
features = ["macros", "signal", "rt-multi-thread"]
 | 
					features = ["macros", "signal", "rt-multi-thread"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					[](https://ci.weirdnatto.in/teams/main/pipelines/singh3) [](https://hub.docker.com/repository/docker/natto17/singh3)
 | 
				
			||||||
 | 
					# Singh3
 | 
				
			||||||
 | 
					My stupid discord bot that I will probably stop maintaining again like I did for the past 8+ months
 | 
				
			||||||
 | 
					Real shit code
 | 
				
			||||||
 | 
					- Not really a useful bot, run at your own risk
 | 
				
			||||||
 | 
					- You need postgresql too
 | 
				
			||||||
 | 
					- Environment Variables
 | 
				
			||||||
 | 
					    - DISCORD_TOKEN={{.your-discord-token}}
 | 
				
			||||||
 | 
					    - DB_URL={{.your-postgresql-db-url}}
 | 
				
			||||||
 | 
					- Image size is kinda large cuz it uses ubuntu for libraries that are dynamically needed
 | 
				
			||||||
							
								
								
									
										85
									
								
								ci/pipeline.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								ci/pipeline.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					resource_types:
 | 
				
			||||||
 | 
					- name: nomad
 | 
				
			||||||
 | 
					  type: registry-image
 | 
				
			||||||
 | 
					  source:
 | 
				
			||||||
 | 
					    repository: natto17/concourse-nomad-resource
 | 
				
			||||||
 | 
					    tag: latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					resources:
 | 
				
			||||||
 | 
					- name: image
 | 
				
			||||||
 | 
					  type: registry-image
 | 
				
			||||||
 | 
					  icon: docker
 | 
				
			||||||
 | 
					  source:
 | 
				
			||||||
 | 
					    repository: ((docker.user))/singh3
 | 
				
			||||||
 | 
					    tag: latest
 | 
				
			||||||
 | 
					    username: ((docker.user))
 | 
				
			||||||
 | 
					    password: ((docker.pass))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- name: nomad-job
 | 
				
			||||||
 | 
					  type: nomad
 | 
				
			||||||
 | 
					  source:
 | 
				
			||||||
 | 
					    url: https://nomad.weirdnatto.in
 | 
				
			||||||
 | 
					    name: singh3
 | 
				
			||||||
 | 
					    token: ((nomad.token))
 | 
				
			||||||
 | 
					    consul_token: ((nomad.consul))
 | 
				
			||||||
 | 
					    vault_token: ((nomad.vault))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- name: repo
 | 
				
			||||||
 | 
					  type: git
 | 
				
			||||||
 | 
					  icon: discord
 | 
				
			||||||
 | 
					  source:
 | 
				
			||||||
 | 
					    uri: https://git.weirdnatto.in/natto1784/singh3.git
 | 
				
			||||||
 | 
					    branch: master
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- name: nix
 | 
				
			||||||
 | 
					  type: registry-image
 | 
				
			||||||
 | 
					  icon: docker
 | 
				
			||||||
 | 
					  source:
 | 
				
			||||||
 | 
					    repository: nixos/nix
 | 
				
			||||||
 | 
					    tag: latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					- name: configure-self
 | 
				
			||||||
 | 
					  public: true
 | 
				
			||||||
 | 
					  plan:
 | 
				
			||||||
 | 
					  - get: repo
 | 
				
			||||||
 | 
					    trigger: true
 | 
				
			||||||
 | 
					  - set_pipeline: self
 | 
				
			||||||
 | 
					    file: repo/ci/pipeline.yml
 | 
				
			||||||
 | 
					- name: singh3
 | 
				
			||||||
 | 
					  plan:
 | 
				
			||||||
 | 
					  - get: repo
 | 
				
			||||||
 | 
					    trigger: true
 | 
				
			||||||
 | 
					    passed: [configure-self]
 | 
				
			||||||
 | 
					  - get: nix
 | 
				
			||||||
 | 
					    trigger: false
 | 
				
			||||||
 | 
					  - task: build
 | 
				
			||||||
 | 
					    image: nix
 | 
				
			||||||
 | 
					    config:
 | 
				
			||||||
 | 
					      params:
 | 
				
			||||||
 | 
					        CACHIX_NAME: ((cachix.name))
 | 
				
			||||||
 | 
					        CACHIX_AUTH_TOKEN: ((cachix.token))
 | 
				
			||||||
 | 
					      inputs:
 | 
				
			||||||
 | 
					      - name: repo
 | 
				
			||||||
 | 
					      outputs:
 | 
				
			||||||
 | 
					      - name: upload
 | 
				
			||||||
 | 
					      platform: linux
 | 
				
			||||||
 | 
					      run:
 | 
				
			||||||
 | 
					        path: sh
 | 
				
			||||||
 | 
					        args:
 | 
				
			||||||
 | 
					        - -c
 | 
				
			||||||
 | 
					        - |
 | 
				
			||||||
 | 
					          nix-env -iA nixpkgs.cachix nixpkgs.gzip
 | 
				
			||||||
 | 
					          cachix use $CACHIX_NAME
 | 
				
			||||||
 | 
					          cachix watch-exec pain nix -- --extra-experimental-features "nix-command flakes" build ./repo
 | 
				
			||||||
 | 
					          nix --extra-experimental-features "nix-command flakes" build ./repo#image -o result
 | 
				
			||||||
 | 
					          gzip -cd < $(readlink result) > ./upload/image.tar
 | 
				
			||||||
 | 
					  - put: image
 | 
				
			||||||
 | 
					    inputs: [upload]
 | 
				
			||||||
 | 
					    params:
 | 
				
			||||||
 | 
					      image: upload/image.tar
 | 
				
			||||||
 | 
					  - put: nomad-job
 | 
				
			||||||
 | 
					    params:
 | 
				
			||||||
 | 
					      job_path: repo/singh3.nomad
 | 
				
			||||||
 | 
					      templating: false
 | 
				
			||||||
 | 
					      restart: true
 | 
				
			||||||
							
								
								
									
										10
									
								
								default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					(import
 | 
				
			||||||
 | 
					  (
 | 
				
			||||||
 | 
					    let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
 | 
				
			||||||
 | 
					    fetchTarball {
 | 
				
			||||||
 | 
					      url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
 | 
				
			||||||
 | 
					      sha256 = lock.nodes.flake-compat.locked.narHash;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					  { src = ./.; }
 | 
				
			||||||
 | 
					).defaultNix
 | 
				
			||||||
							
								
								
									
										108
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										108
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							@@ -1,12 +1,47 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "nodes": {
 | 
					  "nodes": {
 | 
				
			||||||
 | 
					    "cargo2nix": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "flake-utils": "flake-utils",
 | 
				
			||||||
 | 
					        "nixpkgs": "nixpkgs",
 | 
				
			||||||
 | 
					        "rust-overlay": "rust-overlay"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1648397583,
 | 
				
			||||||
 | 
					        "narHash": "sha256-g1Ej9APkfHjGd9ExBDvpmyAvsKcfMOsNH6p95xc8E/Y=",
 | 
				
			||||||
 | 
					        "owner": "cargo2nix",
 | 
				
			||||||
 | 
					        "repo": "cargo2nix",
 | 
				
			||||||
 | 
					        "rev": "4362ae00fe824d120e94dd5d6f6e63969dc3d264",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "cargo2nix",
 | 
				
			||||||
 | 
					        "repo": "cargo2nix",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "flake-utils": {
 | 
					    "flake-utils": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1614513358,
 | 
					        "lastModified": 1638122382,
 | 
				
			||||||
        "narHash": "sha256-LakhOx3S1dRjnh0b5Dg3mbZyH0ToC9I8Y2wKSkBaTzU=",
 | 
					        "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
        "rev": "5466c5bbece17adaab2d82fae80b46e807611bf3",
 | 
					        "rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "flake-utils_2": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1637014545,
 | 
				
			||||||
 | 
					        "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=",
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -16,6 +51,22 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs": {
 | 
					    "nixpkgs": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1638109994,
 | 
				
			||||||
 | 
					        "narHash": "sha256-OpA37PTiPMIqoRJbufbl5rOLII7HeeGcA0yl7FoyCIE=",
 | 
				
			||||||
 | 
					        "owner": "nixos",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "rev": "a284564b7f75ac4db73607db02076e8da9d42c9d",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "nixos",
 | 
				
			||||||
 | 
					        "ref": "release-21.05",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "nixpkgs_2": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1622966049,
 | 
					        "lastModified": 1622966049,
 | 
				
			||||||
        "narHash": "sha256-6g+28v94ISkVk9TBSsITVOnB2slK8plieWPIF2jo/l0=",
 | 
					        "narHash": "sha256-6g+28v94ISkVk9TBSsITVOnB2slK8plieWPIF2jo/l0=",
 | 
				
			||||||
@@ -31,39 +82,66 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs_2": {
 | 
					    "nixpkgs_3": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1617325113,
 | 
					        "lastModified": 1637453606,
 | 
				
			||||||
        "narHash": "sha256-GksR0nvGxfZ79T91UUtWjjccxazv6Yh/MvEJ82v1Xmw=",
 | 
					        "narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=",
 | 
				
			||||||
        "owner": "nixos",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "54c1e44240d8a527a8f4892608c4bce5440c3ecb",
 | 
					        "rev": "8afc4e543663ca0a6a4f496262cd05233737e732",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
        "owner": "NixOS",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "ref": "nixpkgs-unstable",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "root": {
 | 
					    "root": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "nixpkgs": "nixpkgs",
 | 
					        "cargo2nix": "cargo2nix",
 | 
				
			||||||
        "rust-overlay": "rust-overlay",
 | 
					        "nixpkgs": "nixpkgs_2",
 | 
				
			||||||
 | 
					        "rust-overlay": "rust-overlay_2",
 | 
				
			||||||
        "utils": "utils"
 | 
					        "utils": "utils"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "rust-overlay": {
 | 
					    "rust-overlay": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "flake-utils": "flake-utils",
 | 
					        "flake-utils": [
 | 
				
			||||||
        "nixpkgs": "nixpkgs_2"
 | 
					          "cargo2nix",
 | 
				
			||||||
 | 
					          "flake-utils"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "nixpkgs": [
 | 
				
			||||||
 | 
					          "cargo2nix",
 | 
				
			||||||
 | 
					          "nixpkgs"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1623034161,
 | 
					        "lastModified": 1638152159,
 | 
				
			||||||
        "narHash": "sha256-cbw9X+nVFcpIuBga0hkbtzXbW2fyDWBon6oUN/uQmu0=",
 | 
					        "narHash": "sha256-Q0UHsm36cCxk16I/bF1rHJHxjIflESKk2ej76P39j90=",
 | 
				
			||||||
        "owner": "oxalica",
 | 
					        "owner": "oxalica",
 | 
				
			||||||
        "repo": "rust-overlay",
 | 
					        "repo": "rust-overlay",
 | 
				
			||||||
        "rev": "0b952cdfa37f8b0fc70fc75fbd4605227cd0b272",
 | 
					        "rev": "d9a664513558376595e838b21348cdac0ba3115e",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "oxalica",
 | 
				
			||||||
 | 
					        "repo": "rust-overlay",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "rust-overlay_2": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "flake-utils": "flake-utils_2",
 | 
				
			||||||
 | 
					        "nixpkgs": "nixpkgs_3"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1648953213,
 | 
				
			||||||
 | 
					        "narHash": "sha256-kXWcXFwqcvooHjcDoEK4mtvKU/8LuetwhrofU+9KMS0=",
 | 
				
			||||||
 | 
					        "owner": "oxalica",
 | 
				
			||||||
 | 
					        "repo": "rust-overlay",
 | 
				
			||||||
 | 
					        "rev": "caa1a7ea867138d4f4e05bd2f41d707df0a61cde",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								flake.nix
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								flake.nix
									
									
									
									
									
								
							@@ -1,37 +1,54 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  description = "A simple filehost written in rust";
 | 
					  description = "singh3 discord bot";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  inputs = {
 | 
					  inputs = {
 | 
				
			||||||
    nixpkgs.url = github:nixos/nixpkgs/nixos-unstable;
 | 
					    nixpkgs.url = github:nixos/nixpkgs/nixos-unstable;
 | 
				
			||||||
    utils.url = github:numtide/flake-utils;
 | 
					    utils.url = github:numtide/flake-utils;
 | 
				
			||||||
    rust-overlay.url = github:oxalica/rust-overlay;
 | 
					    rust-overlay.url = github:oxalica/rust-overlay;
 | 
				
			||||||
 | 
					    cargo2nix.url = github:cargo2nix/cargo2nix;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  outputs = { self, nixpkgs, utils, rust-overlay }: 
 | 
					  outputs = { self, nixpkgs, utils, rust-overlay, cargo2nix }:
 | 
				
			||||||
    utils.lib.eachDefaultSystem
 | 
					    utils.lib.eachDefaultSystem
 | 
				
			||||||
      (system:
 | 
					      (system:
 | 
				
			||||||
        let
 | 
					        let
 | 
				
			||||||
      overlays = [ (import rust-overlay) ];
 | 
					          overlays =
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					              (import "${cargo2nix}/overlay")
 | 
				
			||||||
 | 
					              rust-overlay.overlay
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          pkgs = import nixpkgs {
 | 
					          pkgs = import nixpkgs {
 | 
				
			||||||
            inherit system overlays;
 | 
					            inherit system overlays;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          rustPkgs = pkgs.rustBuilder.makePackageSet' {
 | 
				
			||||||
 | 
					            rustChannel = "latest";
 | 
				
			||||||
 | 
					            packageFun = import ./Cargo.nix;
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        in
 | 
					        in
 | 
				
			||||||
    {
 | 
					        rec {
 | 
				
			||||||
          devShell = with pkgs; mkShell {
 | 
					          devShell = with pkgs; mkShell {
 | 
				
			||||||
            buildInputs = [
 | 
					            buildInputs = [
 | 
				
			||||||
              rust-bin.nightly.latest.default
 | 
					              rust-bin.nightly.latest.default
 | 
				
			||||||
              rust-analyzer
 | 
					              rust-analyzer
 | 
				
			||||||
 | 
					              postgresql
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
      defaultPackage = pkgs.rustPlatform.buildRustPackage rec {
 | 
					
 | 
				
			||||||
        pname = "singh3";
 | 
					          packages = {
 | 
				
			||||||
        version = "0.1.0";
 | 
					            default = (rustPkgs.workspace.singh3 { }).bin;
 | 
				
			||||||
        src = ./. ;
 | 
					            image = pkgs.dockerTools.buildImage {
 | 
				
			||||||
        nativeBuildInputs = with pkgs; [
 | 
					                name = "singh3";
 | 
				
			||||||
          rust-bin.nightly.latest.default
 | 
					                tag = "latest";
 | 
				
			||||||
        ];
 | 
					                created = "now";
 | 
				
			||||||
        cargoSha256 = "sha256-K+WHOEo6reNfcs7pOZZmHZfZl4pUqlykfTdqgSyVURU=";
 | 
					                contents = [ packages.default ];
 | 
				
			||||||
 | 
					                config.Cmd = [ "/bin/singh3" ];
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          defaultPackage = packages.default;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								init.sql
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								init.sql
									
									
									
									
									
								
							@@ -3,3 +3,11 @@ CREATE TABLE IF NOT EXISTS words (
 | 
				
			|||||||
  name varchar not null,
 | 
					  name varchar not null,
 | 
				
			||||||
  reg varchar not null,
 | 
					  reg varchar not null,
 | 
				
			||||||
  owner varchar );
 | 
					  owner varchar );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE IF NOT EXISTS tags (
 | 
				
			||||||
 | 
					  id serial primary key,
 | 
				
			||||||
 | 
					  name varchar unique not null,
 | 
				
			||||||
 | 
					  value varchar not null,
 | 
				
			||||||
 | 
					  owner varchar );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								singh3.nomad
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								singh3.nomad
									
									
									
									
									
								
							@@ -2,51 +2,70 @@ job "singh3" {
 | 
				
			|||||||
  region      = "global"
 | 
					  region      = "global"
 | 
				
			||||||
  datacenters = ["nazrin"]
 | 
					  datacenters = ["nazrin"]
 | 
				
			||||||
  type        = "service"
 | 
					  type        = "service"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  group "svc" {
 | 
					  group "svc" {
 | 
				
			||||||
    count = 1
 | 
					    count = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    network {
 | 
					    network {
 | 
				
			||||||
      mode = "bridge"
 | 
					      mode = "bridge"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      port "db" {
 | 
					      port "db" {
 | 
				
			||||||
        static = 5454
 | 
					        static = 5454
 | 
				
			||||||
        to     = 5432
 | 
					        to     = 5432
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vault {
 | 
					    vault {
 | 
				
			||||||
      policies = ["singh3-policy"]
 | 
					      policies = ["singh3-policy"]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    service {
 | 
					    service {
 | 
				
			||||||
      name = "singh3-db"
 | 
					      name = "singh3-db"
 | 
				
			||||||
      port = "db"
 | 
					      port = "db"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    task "db" {
 | 
					    task "db" {
 | 
				
			||||||
      template {
 | 
					      template {
 | 
				
			||||||
        data = <<EOF
 | 
					        data = <<EOF
 | 
				
			||||||
{{with secret "kv/data/singh3/db"}}{{.Data.data.pass}}{{end}}
 | 
					{{with secret "kv/data/singh3/db"}}{{.Data.data.pass}}{{end}}
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        destination = "${NOMAD_SECRETS_DIR}/db.pass"
 | 
					        destination = "${NOMAD_SECRETS_DIR}/db.pass"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      driver = "docker"
 | 
					      driver = "docker"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      config {
 | 
					      config {
 | 
				
			||||||
        image   = "postgres:alpine"
 | 
					        image   = "postgres:alpine"
 | 
				
			||||||
        ports   = ["db"]
 | 
					        ports   = ["db"]
 | 
				
			||||||
        volumes = ["/var/lib/nomad-st/postgres-singh3:/var/lib/postgresql/data"]
 | 
					        volumes = ["/var/lib/nomad-st/postgres-singh3:/var/lib/postgresql/data"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      env {
 | 
					      env {
 | 
				
			||||||
        POSTGRES_USER          = "singh3"
 | 
					        POSTGRES_USER          = "singh3"
 | 
				
			||||||
        POSTGRES_PASSWORD_FILE = "${NOMAD_SECRETS_DIR}/db.pass"
 | 
					        POSTGRES_PASSWORD_FILE = "${NOMAD_SECRETS_DIR}/db.pass"
 | 
				
			||||||
        POSTGRES_DB            = "singh3"
 | 
					        POSTGRES_DB            = "singh3"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      resources {
 | 
					      resources {
 | 
				
			||||||
        cpu    = 256
 | 
					        cpu    = 128
 | 
				
			||||||
        memory = 128
 | 
					        memory = 100
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    task "bot" {
 | 
					    task "bot" {
 | 
				
			||||||
      driver = "docker"
 | 
					      driver = "docker"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      config {
 | 
					      config {
 | 
				
			||||||
        image      = "natto17/singh3:latest"
 | 
					        image      = "natto17/singh3:latest"
 | 
				
			||||||
        force_pull = true
 | 
					        force_pull = true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      resources {
 | 
				
			||||||
 | 
					        cpu    = 128
 | 
				
			||||||
 | 
					        memory = 100
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      template {
 | 
					      template {
 | 
				
			||||||
        data = <<EOF
 | 
					        data = <<EOF
 | 
				
			||||||
{{with secret "kv/data/singh3/db"}}
 | 
					{{with secret "kv/data/singh3/db"}}
 | 
				
			||||||
@@ -57,6 +76,7 @@ DISCORD_TOKEN="{{.Data.data.token}}"
 | 
				
			|||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
RUST_BACKTRACE=1
 | 
					RUST_BACKTRACE=1
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        destination = "${NOMAD_SECRETS_DIR}/data.env"
 | 
					        destination = "${NOMAD_SECRETS_DIR}/data.env"
 | 
				
			||||||
        env         = true
 | 
					        env         = true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,50 +1,65 @@
 | 
				
			|||||||
 | 
					use crate::lib::components::make_terminal_components;
 | 
				
			||||||
use core::time::Duration;
 | 
					use core::time::Duration;
 | 
				
			||||||
 | 
					use regex::Regex;
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{
 | 
				
			||||||
 | 
					    builder::CreateEmbed,
 | 
				
			||||||
    collector::component_interaction_collector::ComponentInteractionCollectorBuilder,
 | 
					    collector::component_interaction_collector::ComponentInteractionCollectorBuilder,
 | 
				
			||||||
    framework::standard::{macros::command, Args, CommandResult},
 | 
					    framework::standard::{macros::command, Args, CommandResult},
 | 
				
			||||||
    futures::StreamExt,
 | 
					    futures::StreamExt,
 | 
				
			||||||
    model::{
 | 
					    model::{interactions::InteractionResponseType, prelude::*},
 | 
				
			||||||
        channel::ReactionType,
 | 
					 | 
				
			||||||
        interactions::{ButtonStyle, InteractionData},
 | 
					 | 
				
			||||||
        prelude::*,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    prelude::*,
 | 
					    prelude::*,
 | 
				
			||||||
    utils::Colour,
 | 
					    utils::Colour,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use tokio_postgres::Row;
 | 
					use tokio_postgres::Row;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command]
 | 
					#[command]
 | 
				
			||||||
pub async fn kitna(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
					#[aliases("kitna", "c")]
 | 
				
			||||||
    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
					pub async fn count(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
 | 
				
			||||||
    if query == "" {
 | 
					    if args.len() > 2 || args.len() == 0 {
 | 
				
			||||||
        msg.reply(ctx, "bruh kitna kya?").await?;
 | 
					        msg.reply(ctx, "Please use `,count <word> <user>`").await?;
 | 
				
			||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let query = args.single::<String>().unwrap();
 | 
				
			||||||
 | 
					    let user = if args.len() == 2 {
 | 
				
			||||||
 | 
					        let user = args.single::<UserId>();
 | 
				
			||||||
 | 
					        match user {
 | 
				
			||||||
 | 
					            Ok(id) => match id.to_user(&ctx.http).await {
 | 
				
			||||||
 | 
					                Ok(u) => u,
 | 
				
			||||||
 | 
					                Err(_) => {
 | 
				
			||||||
 | 
					                    msg.reply(ctx, "No such user").await?;
 | 
				
			||||||
 | 
					                    return Ok(());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            Err(_) => {
 | 
				
			||||||
 | 
					                msg.reply(ctx, "No such user").await?;
 | 
				
			||||||
 | 
					                return Ok(());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        msg.author.clone()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let data_read = ctx.data.read().await;
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
    let db = data_read
 | 
					    let db = data_read
 | 
				
			||||||
        .get::<crate::Database>()
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
        .expect("Expected Database in TypeMap.")
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
        .clone();
 | 
					        .clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let id = msg.author.id.to_string();
 | 
					    let id = user.id.to_string();
 | 
				
			||||||
    let mut query_helper = db
 | 
					    let mut query_helper = db
 | 
				
			||||||
        .query(
 | 
					        .query("SELECT name FROM words WHERE $1 ~ reg", &[&query])
 | 
				
			||||||
            format!("select name from words where '{}' ~ reg", query).as_str(),
 | 
					 | 
				
			||||||
            &[],
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if query_helper.is_empty() {
 | 
					    if query_helper.is_empty() {
 | 
				
			||||||
        query_helper = db
 | 
					        query_helper = db
 | 
				
			||||||
            .query(
 | 
					            .query("SELECT name FROM words WHERE name=$1", &[&query])
 | 
				
			||||||
                format!("select name from words where name='{}'", query).as_str(),
 | 
					 | 
				
			||||||
                &[],
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
        if query_helper.is_empty() {
 | 
					        if query_helper.is_empty() {
 | 
				
			||||||
            msg.reply(
 | 
					            msg.reply(
 | 
				
			||||||
                ctx,
 | 
					                ctx,
 | 
				
			||||||
                format!(
 | 
					                format!(
 | 
				
			||||||
                    "No entry for '{}' found. If you want to add it, run ',count add {}&<regex>'",
 | 
					                    "No entry for '{}' found. If you want to add it, run `,cadd {} <regex>`",
 | 
				
			||||||
                    query, query
 | 
					                    query, query
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
@@ -59,42 +74,49 @@ pub async fn kitna(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
    for row in query_helper {
 | 
					    for row in query_helper {
 | 
				
			||||||
        let name: &str = row.get(0);
 | 
					        let name: &str = row.get(0);
 | 
				
			||||||
        let query_result: i32 = db
 | 
					        let count_query = db
 | 
				
			||||||
            .query_one(
 | 
					            .query(
 | 
				
			||||||
                format!("select count from user{} where name='{}'", id, name).as_str(),
 | 
					                format!("SELECT count FROM user{} WHERE name=$1", id).as_str(),
 | 
				
			||||||
                &[],
 | 
					                &[&name],
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            .await?
 | 
					            .await?;
 | 
				
			||||||
            .get(0);
 | 
					        let query_result: i32 = if count_query.is_empty() {
 | 
				
			||||||
        reply = reply + &format!("\n{} count for you: {}", name, query_result);
 | 
					            0
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            count_query[0].get(0)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        reply += &format!("\n{} count for {}: {}", name, user.name, query_result);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    msg.reply(ctx, reply).await?;
 | 
					    msg.reply(ctx, reply).await?;
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command]
 | 
					#[command]
 | 
				
			||||||
pub async fn add(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
					pub async fn cadd(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			||||||
    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
					    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
				
			||||||
    let queries = query.splitn(2, "&").collect::<Vec<&str>>();
 | 
					    let queries = query.splitn(2, " ").collect::<Vec<&str>>();
 | 
				
			||||||
    if queries.len() != 2 {
 | 
					    if queries.len() != 2 {
 | 
				
			||||||
        msg.reply(ctx, "Please use the proper syntax: `,count add <name>&<regex>`\nIf you don't know what regex is, just do: `,count add <name>&<name>`")
 | 
					        msg.reply(ctx, "Please use the proper syntax: `,cadd <name> <regex>`\nIf you don't know what regex is, just do: `,cadd <name> <name>`")
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if queries[1].contains(" ") {
 | 
					    let r = Regex::new(&format!("(?i){}", queries[1]));
 | 
				
			||||||
        msg.reply(ctx, "Not a valid regex").await?;
 | 
					
 | 
				
			||||||
 | 
					    if r.is_err() {
 | 
				
			||||||
 | 
					        msg.reply(ctx, "Please enter a valid regex").await?;
 | 
				
			||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let reg = r.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let data_read = ctx.data.read().await;
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
    let db = data_read
 | 
					    let db = data_read
 | 
				
			||||||
        .get::<crate::Database>()
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
        .expect("Expected Database in TypeMap.")
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
        .clone();
 | 
					        .clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let check_existense = db
 | 
					    let check_existense = db
 | 
				
			||||||
        .query(
 | 
					        .query("SELECT name, reg FROM words WHERE name=$1", &[&queries[0]])
 | 
				
			||||||
            format!("select name, reg from words where name='{}'", queries[0]).as_str(),
 | 
					 | 
				
			||||||
            &[],
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
    if check_existense.len() != 0 {
 | 
					    if check_existense.len() != 0 {
 | 
				
			||||||
        let reg: String = check_existense[0].get(1);
 | 
					        let reg: String = check_existense[0].get(1);
 | 
				
			||||||
@@ -106,14 +128,8 @@ pub async fn add(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			|||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    db.execute(
 | 
					    db.execute(
 | 
				
			||||||
        format!(
 | 
					        "INSERT INTO words(name, reg, owner) VALUES($1, $2, $3)",
 | 
				
			||||||
            "insert into words(name, reg, owner) values('{}','(?i){}', '{}')",
 | 
					        &[&queries[0], ®.to_string(), &msg.author.id.to_string()],
 | 
				
			||||||
            queries[0],
 | 
					 | 
				
			||||||
            queries[1],
 | 
					 | 
				
			||||||
            msg.author.id.to_string()
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .as_str(),
 | 
					 | 
				
			||||||
        &[],
 | 
					 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .await?;
 | 
					    .await?;
 | 
				
			||||||
    msg.reply(ctx, "Added").await?;
 | 
					    msg.reply(ctx, "Added").await?;
 | 
				
			||||||
@@ -121,7 +137,8 @@ pub async fn add(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command]
 | 
					#[command]
 | 
				
			||||||
pub async fn rm(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
					#[aliases("crm")]
 | 
				
			||||||
 | 
					pub async fn cremove(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			||||||
    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
					    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
				
			||||||
    if query == "" {
 | 
					    if query == "" {
 | 
				
			||||||
        msg.reply(ctx, "remove what?").await?;
 | 
					        msg.reply(ctx, "remove what?").await?;
 | 
				
			||||||
@@ -133,10 +150,7 @@ pub async fn rm(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			|||||||
        .expect("Expected Database in TypeMap.")
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
        .clone();
 | 
					        .clone();
 | 
				
			||||||
    let owner = db
 | 
					    let owner = db
 | 
				
			||||||
        .query(
 | 
					        .query("SELECT owner FROM words WHERE name=$1", &[&query])
 | 
				
			||||||
            format!("select owner from words where name = '{}'", query).as_str(),
 | 
					 | 
				
			||||||
            &[],
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
    if owner.len() == 1 {
 | 
					    if owner.len() == 1 {
 | 
				
			||||||
        let owner_id: String = owner[0].get(0);
 | 
					        let owner_id: String = owner[0].get(0);
 | 
				
			||||||
@@ -145,24 +159,18 @@ pub async fn rm(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			|||||||
            return Ok(());
 | 
					            return Ok(());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    db.execute(
 | 
					    db.execute("DELETE FROM words WHERE name=$1", &[&query])
 | 
				
			||||||
        format!("delete from words where name='{}'", query,).as_str(),
 | 
					 | 
				
			||||||
        &[],
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
    msg.reply(ctx, "Deleted if it existed").await?;
 | 
					    msg.reply(ctx, "Deleted if it existed").await?;
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command]
 | 
					#[command]
 | 
				
			||||||
pub async fn change(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
					pub async fn cedit(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			||||||
    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
					    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
				
			||||||
    let queries = query.splitn(2, "&").collect::<Vec<&str>>();
 | 
					    let queries = query.splitn(2, "&").collect::<Vec<&str>>();
 | 
				
			||||||
    if queries.len() != 2 {
 | 
					    if queries.len() != 2 {
 | 
				
			||||||
        msg.reply(
 | 
					        msg.reply(ctx, "Please use the proper syntax\n,cedit <name>&<regex>")
 | 
				
			||||||
            ctx,
 | 
					 | 
				
			||||||
            "Please use the proper syntax\n,count change <name>&<regex>",
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -176,10 +184,7 @@ pub async fn change(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			|||||||
        .expect("Expected Database in TypeMap.")
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
        .clone();
 | 
					        .clone();
 | 
				
			||||||
    let owner = db
 | 
					    let owner = db
 | 
				
			||||||
        .query(
 | 
					        .query("SELECT owner FROM words WHERE name=$1", &[&queries[0]])
 | 
				
			||||||
            format!("select owner from words where name = '{}'", queries[0]).as_str(),
 | 
					 | 
				
			||||||
            &[],
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
    if owner.len() == 1 {
 | 
					    if owner.len() == 1 {
 | 
				
			||||||
        let owner_id: String = owner[0].get(0);
 | 
					        let owner_id: String = owner[0].get(0);
 | 
				
			||||||
@@ -189,106 +194,93 @@ pub async fn change(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    db.execute(
 | 
					    db.execute(
 | 
				
			||||||
        format!(
 | 
					        "UPDATE words SET reg=$1 WHERE name=$2",
 | 
				
			||||||
            "update words set reg='(?i){}' where name='{}'",
 | 
					        &[&("(?i)".to_string() + queries[1]), &queries[0]],
 | 
				
			||||||
            queries[1], queries[0]
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .as_str(),
 | 
					 | 
				
			||||||
        &[],
 | 
					 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .await?;
 | 
					    .await?;
 | 
				
			||||||
    msg.reply(ctx, "Changed the value if it existed").await?;
 | 
					    msg.reply(ctx, "Changed the value if it existed").await?;
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro_rules! make_embed {
 | 
					fn make_list_embed(cur: usize, group: &[Row]) -> CreateEmbed {
 | 
				
			||||||
    ($e: expr, $cur: expr, $group: expr) => {{
 | 
					    let mut e = CreateEmbed::default();
 | 
				
			||||||
        $e = $e
 | 
					    e.title(format!("List of words: Page {}", cur))
 | 
				
			||||||
            .title(format!("List of words: Page {}", $cur))
 | 
					 | 
				
			||||||
        .color(Colour::TEAL);
 | 
					        .color(Colour::TEAL);
 | 
				
			||||||
        for row in $group {
 | 
					    for row in group {
 | 
				
			||||||
            let idx: i32 = row.get(0);
 | 
					        let idx: i64 = row.get(0);
 | 
				
			||||||
        let name: String = row.get(1);
 | 
					        let name: String = row.get(1);
 | 
				
			||||||
            let owner_id: String = row.get(3);
 | 
					        let owner_id: String = row.get(2);
 | 
				
			||||||
            $e = $e.field(
 | 
					        e.field(
 | 
				
			||||||
            format!("{}. {}", idx, name),
 | 
					            format!("{}. {}", idx, name),
 | 
				
			||||||
            format!(" by <@{}>", owner_id),
 | 
					            format!(" by <@{}>", owner_id),
 | 
				
			||||||
                true,
 | 
					            false,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        $e
 | 
					    e
 | 
				
			||||||
    }};
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
macro_rules! make_terminal_components {
 | 
					 | 
				
			||||||
    ($c: expr, $terminal: expr ) => {{
 | 
					 | 
				
			||||||
        $c.create_action_row(|ar| {
 | 
					 | 
				
			||||||
            ar.create_button(|b| {
 | 
					 | 
				
			||||||
                b.style(ButtonStyle::Primary)
 | 
					 | 
				
			||||||
                    .label("Prev")
 | 
					 | 
				
			||||||
                    .emoji(ReactionType::Unicode("\u{2B05}".to_string()))
 | 
					 | 
				
			||||||
                    .custom_id("prev")
 | 
					 | 
				
			||||||
                    .disabled($terminal == "first")
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .create_button(|b| {
 | 
					 | 
				
			||||||
                b.style(ButtonStyle::Primary)
 | 
					 | 
				
			||||||
                    .label("Next")
 | 
					 | 
				
			||||||
                    .emoji(ReactionType::Unicode("\u{27A1}".to_string()))
 | 
					 | 
				
			||||||
                    .custom_id("next")
 | 
					 | 
				
			||||||
                    .disabled($terminal == "last")
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }};
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command]
 | 
					#[command]
 | 
				
			||||||
pub async fn ls(ctx: &Context, msg: &Message, _: Args) -> CommandResult {
 | 
					#[aliases("cls")]
 | 
				
			||||||
 | 
					pub async fn clist(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let size = if args.len() > 0 {
 | 
				
			||||||
 | 
					        args.single::<usize>()?
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        5usize
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if size > 15 {
 | 
				
			||||||
 | 
					        msg.reply(ctx, "Please input a number less than 15").await?;
 | 
				
			||||||
 | 
					        ()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let data_read = ctx.data.read().await;
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
    let db = data_read
 | 
					    let db = data_read
 | 
				
			||||||
        .get::<crate::Database>()
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
        .expect("Expected Database in TypeMap.")
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
        .clone();
 | 
					        .clone();
 | 
				
			||||||
    let rows = db.query("select * from words", &[]).await?;
 | 
					
 | 
				
			||||||
 | 
					    let rows = db
 | 
				
			||||||
 | 
					        .query(
 | 
				
			||||||
 | 
					            "SELECT ROW_NUMBER() OVER (ORDER BY id), name, owner FROM words",
 | 
				
			||||||
 | 
					            &[],
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if rows.is_empty() {
 | 
					    if rows.is_empty() {
 | 
				
			||||||
        msg.reply(ctx, "No words stored").await?;
 | 
					        msg.reply(ctx, "No words stored").await?;
 | 
				
			||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    let groups: Vec<&[Row]> = rows.chunks(5).collect();
 | 
					 | 
				
			||||||
    let mut cur = 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let groups: Vec<&[Row]> = rows.chunks(size).collect();
 | 
				
			||||||
 | 
					    let mut cur = 1;
 | 
				
			||||||
    let message = msg
 | 
					    let message = msg
 | 
				
			||||||
        .channel_id
 | 
					        .channel_id
 | 
				
			||||||
        .send_message(ctx, |m| {
 | 
					        .send_message(ctx, |m| {
 | 
				
			||||||
            m.embed(|mut e| make_embed!(e, cur, groups[cur - 1]))
 | 
					            m.set_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
                .components(|c| make_terminal_components!(c, "first"))
 | 
					                .set_components(make_terminal_components("first", groups.len()))
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut collector = ComponentInteractionCollectorBuilder::new(&ctx)
 | 
					    let mut collector = ComponentInteractionCollectorBuilder::new(&ctx)
 | 
				
			||||||
        .timeout(Duration::from_secs(90))
 | 
					        .timeout(Duration::from_secs(90))
 | 
				
			||||||
        .author_id(msg.author.id)
 | 
					        .author_id(msg.author.id)
 | 
				
			||||||
        .message_id(message.id)
 | 
					        .message_id(message.id)
 | 
				
			||||||
        .await;
 | 
					        .await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while let Some(interaction) = collector.next().await {
 | 
					    while let Some(interaction) = collector.next().await {
 | 
				
			||||||
        if let InteractionData::MessageComponent(component) = interaction.data.as_ref().unwrap() {
 | 
					        match interaction.data.custom_id.as_ref() {
 | 
				
			||||||
            match component.custom_id.as_ref() {
 | 
					 | 
				
			||||||
            "next" => {
 | 
					            "next" => {
 | 
				
			||||||
                if cur != groups.len() {
 | 
					                if cur != groups.len() {
 | 
				
			||||||
 | 
					                    cur += 1;
 | 
				
			||||||
                    let _ = interaction
 | 
					                    let _ = interaction
 | 
				
			||||||
                        .create_interaction_response(&ctx, |r| {
 | 
					                        .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
                            r.kind(InteractionResponseType::UpdateMessage)
 | 
					                            r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
                                .interaction_response_data(|m| {
 | 
					                                .interaction_response_data(|m| {
 | 
				
			||||||
                                        cur += 1;
 | 
					                                    m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
                                        m.create_embed(|mut e| make_embed!(e, cur, groups[cur - 1]))
 | 
					                                        .set_components(make_terminal_components(
 | 
				
			||||||
                                            .components(|c| {
 | 
					                                            if cur == groups.len() { "last" } else { "mid" },
 | 
				
			||||||
                                                make_terminal_components!(
 | 
					                                            groups.len(),
 | 
				
			||||||
                                                    c,
 | 
					                                        ))
 | 
				
			||||||
                                                    if cur == groups.len() {
 | 
					 | 
				
			||||||
                                                        "last"
 | 
					 | 
				
			||||||
                                                    } else {
 | 
					 | 
				
			||||||
                                                        "mid"
 | 
					 | 
				
			||||||
                                                    }
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            })
 | 
					 | 
				
			||||||
                                })
 | 
					                                })
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                        .await;
 | 
					                        .await;
 | 
				
			||||||
@@ -296,25 +288,71 @@ pub async fn ls(ctx: &Context, msg: &Message, _: Args) -> CommandResult {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            "prev" => {
 | 
					            "prev" => {
 | 
				
			||||||
                if cur != 1 {
 | 
					                if cur != 1 {
 | 
				
			||||||
 | 
					                    cur -= 1;
 | 
				
			||||||
                    let _ = interaction
 | 
					                    let _ = interaction
 | 
				
			||||||
                        .create_interaction_response(&ctx, |r| {
 | 
					                        .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
                            r.kind(InteractionResponseType::UpdateMessage)
 | 
					                            r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
                                .interaction_response_data(|m| {
 | 
					                                .interaction_response_data(|m| {
 | 
				
			||||||
                                        cur -= 1;
 | 
					                                    m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
                                        m.create_embed(|mut e| make_embed!(e, cur, groups[cur - 1]))
 | 
					                                        .set_components(make_terminal_components(
 | 
				
			||||||
                                            .components(|c| {
 | 
					                                            if cur == 1 { "first" } else { "mid" },
 | 
				
			||||||
                                                make_terminal_components!(
 | 
					                                            groups.len(),
 | 
				
			||||||
                                                    c,
 | 
					                                        ))
 | 
				
			||||||
                                                    if cur == 1 { "first" } else { "mid" }
 | 
					 | 
				
			||||||
                                                )
 | 
					 | 
				
			||||||
                                            })
 | 
					 | 
				
			||||||
                                })
 | 
					                                })
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                        .await;
 | 
					                        .await;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                _ => {}
 | 
					            "first" => {
 | 
				
			||||||
 | 
					                cur = 1;
 | 
				
			||||||
 | 
					                let _ = interaction
 | 
				
			||||||
 | 
					                    .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                        r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                            .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                    .set_components(make_terminal_components("first", groups.len()))
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .await;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            "last" => {
 | 
				
			||||||
 | 
					                cur = groups.len();
 | 
				
			||||||
 | 
					                let _ = interaction
 | 
				
			||||||
 | 
					                    .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                        r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                            .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                    .set_components(make_terminal_components("last", groups.len()))
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "delete" => {
 | 
				
			||||||
 | 
					                message.delete(ctx).await?;
 | 
				
			||||||
 | 
					                msg.delete(ctx).await?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "range" => {
 | 
				
			||||||
 | 
					                cur = interaction.data.values[0].parse().unwrap();
 | 
				
			||||||
 | 
					                let _ = interaction
 | 
				
			||||||
 | 
					                    .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                        r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                            .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                    .set_components(make_terminal_components(
 | 
				
			||||||
 | 
					                                        if cur == 1 {
 | 
				
			||||||
 | 
					                                            "first"
 | 
				
			||||||
 | 
					                                        } else if cur == groups.len() {
 | 
				
			||||||
 | 
					                                            "last"
 | 
				
			||||||
 | 
					                                        } else {
 | 
				
			||||||
 | 
					                                            "mid"
 | 
				
			||||||
 | 
					                                        },
 | 
				
			||||||
 | 
					                                        groups.len(),
 | 
				
			||||||
 | 
					                                    ))
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => {}
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,6 @@
 | 
				
			|||||||
use serenity::prelude::*;
 | 
					use serenity::framework::standard::{macros::command, CommandResult};
 | 
				
			||||||
use serenity::model::prelude::*;
 | 
					use serenity::model::prelude::*;
 | 
				
			||||||
use serenity::framework::standard::{
 | 
					use serenity::prelude::*;
 | 
				
			||||||
    CommandResult,
 | 
					 | 
				
			||||||
    macros::command
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command]
 | 
					#[command]
 | 
				
			||||||
pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
 | 
					pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
pub mod general;
 | 
					 | 
				
			||||||
pub mod count;
 | 
					pub mod count;
 | 
				
			||||||
 | 
					pub mod general;
 | 
				
			||||||
pub mod minigames;
 | 
					pub mod minigames;
 | 
				
			||||||
 | 
					pub mod tags;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										394
									
								
								src/commands/tags.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										394
									
								
								src/commands/tags.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,394 @@
 | 
				
			|||||||
 | 
					use crate::lib::{components::make_terminal_components, messages::ExtractInfo};
 | 
				
			||||||
 | 
					use core::time::Duration;
 | 
				
			||||||
 | 
					use serenity::{
 | 
				
			||||||
 | 
					    builder::CreateEmbed,
 | 
				
			||||||
 | 
					    collector::component_interaction_collector::ComponentInteractionCollectorBuilder,
 | 
				
			||||||
 | 
					    framework::standard::{macros::command, Args, CommandResult},
 | 
				
			||||||
 | 
					    futures::StreamExt,
 | 
				
			||||||
 | 
					    model::{interactions::InteractionResponseType, prelude::*},
 | 
				
			||||||
 | 
					    prelude::*,
 | 
				
			||||||
 | 
					    utils::Colour,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use tokio_postgres::Row;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GUILD_ID: u64 = 874699899067838535;
 | 
				
			||||||
 | 
					const ROLE_ID: u64 = 957155053184102400;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[command]
 | 
				
			||||||
 | 
					#[aliases("t")]
 | 
				
			||||||
 | 
					pub async fn tag(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let query: String = args.raw().collect::<Vec<&str>>().join("");
 | 
				
			||||||
 | 
					    if query == "" {
 | 
				
			||||||
 | 
					        msg.reply(ctx, "Mention the tag retard").await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
 | 
					    let db = data_read
 | 
				
			||||||
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
 | 
					        .clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let query_helper = db
 | 
				
			||||||
 | 
					        .query("SELECT name, value FROM tags WHERE name=$1", &[&query])
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if query_helper.is_empty() {
 | 
				
			||||||
 | 
					        const DIST_LIMIT: i32 = 2;
 | 
				
			||||||
 | 
					        let leven = db
 | 
				
			||||||
 | 
					            .query(
 | 
				
			||||||
 | 
					                "SELECT name, levenshtein_less_equal(name, $1, $2) AS lev FROM tags ORDER BY lev LIMIT 1 ",
 | 
				
			||||||
 | 
					                &[&query, &DIST_LIMIT],
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let dist: i32 = leven[0].get(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let l = if dist > DIST_LIMIT {
 | 
				
			||||||
 | 
					            "".to_string()
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            let leven_name: String = leven[0].get(0);
 | 
				
			||||||
 | 
					            format!("\nDid you mean `{}`?", leven_name)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        msg.reply(
 | 
				
			||||||
 | 
					            ctx,
 | 
				
			||||||
 | 
					            format!(
 | 
				
			||||||
 | 
					                "No entry for '{}' found. If you want to add it, run `,tadd {} <value>`{}",
 | 
				
			||||||
 | 
					                query, query, l
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    let value: String = query_helper[0].get(1);
 | 
				
			||||||
 | 
					    msg.reply(ctx, value).await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[command]
 | 
				
			||||||
 | 
					pub async fn tadd(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let tag_value = msg.extract_text(2, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if tag_value.is_none() {
 | 
				
			||||||
 | 
					        msg.reply(
 | 
				
			||||||
 | 
					            ctx,
 | 
				
			||||||
 | 
					            "Please use the proper syntax: `,tadd <name> <value>` or attach something",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let tag_name = args.single::<String>().unwrap();
 | 
				
			||||||
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
 | 
					    let db = data_read
 | 
				
			||||||
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
 | 
					        .clone();
 | 
				
			||||||
 | 
					    let check_existense = db
 | 
				
			||||||
 | 
					        .query("SELECT name FROM tags WHERE name=$1", &[&tag_name])
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    if check_existense.len() != 0 {
 | 
				
			||||||
 | 
					        msg.reply(ctx, format!("This tag already exists")).await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    db.execute(
 | 
				
			||||||
 | 
					        "INSERT INTO tags(name, value, owner) VALUES($1, $2, $3)",
 | 
				
			||||||
 | 
					        &[&tag_name, &tag_value, &msg.author.id.to_string()],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    msg.reply(ctx, "Added").await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[command]
 | 
				
			||||||
 | 
					#[aliases("tcp")]
 | 
				
			||||||
 | 
					pub async fn tcopy(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let queries: Vec<&str> = args.raw().collect::<Vec<&str>>();
 | 
				
			||||||
 | 
					    if queries.len() != 2 {
 | 
				
			||||||
 | 
					        msg.reply(
 | 
				
			||||||
 | 
					            ctx,
 | 
				
			||||||
 | 
					            "Please use the proper syntax: `,tcopy <original> <new>`",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
 | 
					    let db = data_read
 | 
				
			||||||
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
 | 
					        .clone();
 | 
				
			||||||
 | 
					    let check_existense = db
 | 
				
			||||||
 | 
					        .query("SELECT name FROM tags WHERE name=$1", &[&queries[0]])
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    if check_existense.len() == 0 {
 | 
				
			||||||
 | 
					        msg.reply(ctx, format!("This tag does not exist")).await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    db.execute(
 | 
				
			||||||
 | 
					        "INSERT INTO tags(name, value, owner) SELECT $1, value, $2 FROM tags WHERE name=$3",
 | 
				
			||||||
 | 
					        &[&queries[1], &msg.author.id.to_string(), &queries[0]],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    msg.reply(ctx, format!("Copied {} to {}", queries[0], queries[1]))
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[command]
 | 
				
			||||||
 | 
					#[aliases("trm")]
 | 
				
			||||||
 | 
					pub async fn tremove(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let query: String = args.raw().collect::<Vec<&str>>().join(" ");
 | 
				
			||||||
 | 
					    if query == "" {
 | 
				
			||||||
 | 
					        msg.reply(ctx, "remove what?").await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
 | 
					    let db = data_read
 | 
				
			||||||
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
 | 
					        .clone();
 | 
				
			||||||
 | 
					    let owner = db
 | 
				
			||||||
 | 
					        .query("SELECT owner FROM tags WHERE name=$1", &[&query])
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    if owner.len() == 1 {
 | 
				
			||||||
 | 
					        let owner_id: String = owner[0].get(0);
 | 
				
			||||||
 | 
					        if owner_id != msg.author.id.to_string()
 | 
				
			||||||
 | 
					            && !msg.author.has_role(&ctx.http, GUILD_ID, ROLE_ID).await?
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            msg.reply(ctx, "You don't even own this tag").await?;
 | 
				
			||||||
 | 
					            return Ok(());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    db.execute("DELETE FROM tags WHERE name=$1", &[&query])
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    msg.reply(ctx, format!("Deleted {} if it existed", query))
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[command]
 | 
				
			||||||
 | 
					pub async fn tedit(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let tag_value = msg.extract_text(2, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if tag_value.is_none() {
 | 
				
			||||||
 | 
					        msg.reply(
 | 
				
			||||||
 | 
					            ctx,
 | 
				
			||||||
 | 
					            "Please use the proper syntax: `,tadd <name> <value>` or attach something",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let tag_name = args.single::<String>().unwrap();
 | 
				
			||||||
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
 | 
					    let db = data_read
 | 
				
			||||||
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
 | 
					        .clone();
 | 
				
			||||||
 | 
					    let owner = db
 | 
				
			||||||
 | 
					        .query("SELECT owner FROM tags WHERE name=$1", &[&tag_name])
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    if owner.len() == 1 {
 | 
				
			||||||
 | 
					        let owner_id: String = owner[0].get(0);
 | 
				
			||||||
 | 
					        if owner_id != msg.author.id.to_string()
 | 
				
			||||||
 | 
					            && !msg.author.has_role(&ctx.http, GUILD_ID, ROLE_ID).await?
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            msg.reply(ctx, "You don't even own this tag").await?;
 | 
				
			||||||
 | 
					            return Ok(());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    db.execute(
 | 
				
			||||||
 | 
					        "UPDATE tags SET value=$1 WHERE name=$2",
 | 
				
			||||||
 | 
					        &[&tag_value, &tag_name],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    msg.reply(ctx, "Changed the value if it existed").await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn make_list_embed(cur: usize, group: &[Row]) -> CreateEmbed {
 | 
				
			||||||
 | 
					    let mut e = CreateEmbed::default();
 | 
				
			||||||
 | 
					    e.title(format!("List of tags: Page {}", cur))
 | 
				
			||||||
 | 
					        .color(Colour::FABLED_PINK);
 | 
				
			||||||
 | 
					    for row in group {
 | 
				
			||||||
 | 
					        let idx: i64 = row.get(0);
 | 
				
			||||||
 | 
					        let name: String = row.get(1);
 | 
				
			||||||
 | 
					        let owner_id: String = row.get(2);
 | 
				
			||||||
 | 
					        e.field(
 | 
				
			||||||
 | 
					            format!("{}. {}", idx, name),
 | 
				
			||||||
 | 
					            format!(" by <@{}>", owner_id),
 | 
				
			||||||
 | 
					            false,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[command]
 | 
				
			||||||
 | 
					#[aliases("tls")]
 | 
				
			||||||
 | 
					pub async fn tlist(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let size = if args.len() > 0 {
 | 
				
			||||||
 | 
					        args.single::<usize>()?
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        5usize
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if size > 15 {
 | 
				
			||||||
 | 
					        msg.reply(ctx, "Please input a number less than 15").await?;
 | 
				
			||||||
 | 
					        ()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
 | 
					    let db = data_read
 | 
				
			||||||
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
 | 
					        .clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let rows = db
 | 
				
			||||||
 | 
					        .query(
 | 
				
			||||||
 | 
					            "SELECT ROW_NUMBER() OVER (ORDER BY id), name, owner FROM tags",
 | 
				
			||||||
 | 
					            &[],
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if rows.is_empty() {
 | 
				
			||||||
 | 
					        msg.reply(ctx, "No tags stored").await?;
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let groups: Vec<&[Row]> = rows.chunks(size).collect();
 | 
				
			||||||
 | 
					    let mut cur = 1;
 | 
				
			||||||
 | 
					    let message = msg
 | 
				
			||||||
 | 
					        .channel_id
 | 
				
			||||||
 | 
					        .send_message(ctx, |m| {
 | 
				
			||||||
 | 
					            m.set_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                .set_components(make_terminal_components("first", groups.len()))
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut collector = ComponentInteractionCollectorBuilder::new(&ctx)
 | 
				
			||||||
 | 
					        .timeout(Duration::from_secs(90))
 | 
				
			||||||
 | 
					        .author_id(msg.author.id)
 | 
				
			||||||
 | 
					        .message_id(message.id)
 | 
				
			||||||
 | 
					        .await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while let Some(interaction) = collector.next().await {
 | 
				
			||||||
 | 
					        match interaction.data.custom_id.as_ref() {
 | 
				
			||||||
 | 
					            "next" => {
 | 
				
			||||||
 | 
					                if cur != groups.len() {
 | 
				
			||||||
 | 
					                    cur += 1;
 | 
				
			||||||
 | 
					                    let _ = interaction
 | 
				
			||||||
 | 
					                        .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                            r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                                .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                    m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                        .set_components(make_terminal_components(
 | 
				
			||||||
 | 
					                                            if cur == groups.len() { "last" } else { "mid" },
 | 
				
			||||||
 | 
					                                            groups.len(),
 | 
				
			||||||
 | 
					                                        ))
 | 
				
			||||||
 | 
					                                })
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        .await;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "prev" => {
 | 
				
			||||||
 | 
					                if cur != 1 {
 | 
				
			||||||
 | 
					                    cur -= 1;
 | 
				
			||||||
 | 
					                    let _ = interaction
 | 
				
			||||||
 | 
					                        .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                            r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                                .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                    m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                        .set_components(make_terminal_components(
 | 
				
			||||||
 | 
					                                            if cur == 1 { "first" } else { "mid" },
 | 
				
			||||||
 | 
					                                            groups.len(),
 | 
				
			||||||
 | 
					                                        ))
 | 
				
			||||||
 | 
					                                })
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        .await;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "first" => {
 | 
				
			||||||
 | 
					                cur = 1;
 | 
				
			||||||
 | 
					                let _ = interaction
 | 
				
			||||||
 | 
					                    .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                        r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                            .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                    .set_components(make_terminal_components("first", groups.len()))
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "last" => {
 | 
				
			||||||
 | 
					                cur = groups.len();
 | 
				
			||||||
 | 
					                let _ = interaction
 | 
				
			||||||
 | 
					                    .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                        r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                            .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                    .set_components(make_terminal_components("last", groups.len()))
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "delete" => {
 | 
				
			||||||
 | 
					                message.delete(ctx).await?;
 | 
				
			||||||
 | 
					                msg.delete(ctx).await?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            "range" => {
 | 
				
			||||||
 | 
					                cur = interaction.data.values[0].parse().unwrap();
 | 
				
			||||||
 | 
					                let _ = interaction
 | 
				
			||||||
 | 
					                    .create_interaction_response(&ctx, |r| {
 | 
				
			||||||
 | 
					                        r.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                            .interaction_response_data(|m| {
 | 
				
			||||||
 | 
					                                m.add_embed(make_list_embed(cur, groups[cur - 1]))
 | 
				
			||||||
 | 
					                                    .set_components(make_terminal_components(
 | 
				
			||||||
 | 
					                                        if cur == 1 {
 | 
				
			||||||
 | 
					                                            "first"
 | 
				
			||||||
 | 
					                                        } else if cur == groups.len() {
 | 
				
			||||||
 | 
					                                            "last"
 | 
				
			||||||
 | 
					                                        } else {
 | 
				
			||||||
 | 
					                                            "mid"
 | 
				
			||||||
 | 
					                                        },
 | 
				
			||||||
 | 
					                                        groups.len(),
 | 
				
			||||||
 | 
					                                    ))
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => {}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[command]
 | 
				
			||||||
 | 
					#[aliases(trand)]
 | 
				
			||||||
 | 
					pub async fn trandom(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
				
			||||||
 | 
					    let data_read = ctx.data.read().await;
 | 
				
			||||||
 | 
					    let db = data_read
 | 
				
			||||||
 | 
					        .get::<crate::Database>()
 | 
				
			||||||
 | 
					        .expect("Expected Database in TypeMap.")
 | 
				
			||||||
 | 
					        .clone();
 | 
				
			||||||
 | 
					    let rand = db
 | 
				
			||||||
 | 
					        .query(
 | 
				
			||||||
 | 
					            "SELECT name, value, owner FROM tags OFFSET floor(random() * (SELECT COUNT(*) FROM tags)) LIMIT 1",
 | 
				
			||||||
 | 
					            &[],
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					    let name: String = rand[0].get(0);
 | 
				
			||||||
 | 
					    let value: String = rand[0].get(1);
 | 
				
			||||||
 | 
					    let owner: String = rand[0].get(2);
 | 
				
			||||||
 | 
					    let user_id = UserId::from(owner.parse::<u64>().unwrap());
 | 
				
			||||||
 | 
					    msg.reply(
 | 
				
			||||||
 | 
					        ctx,
 | 
				
			||||||
 | 
					        format!(
 | 
				
			||||||
 | 
					            "{}'s tag {}: \n{}",
 | 
				
			||||||
 | 
					            user_id.to_user(&ctx.http).await?.name,
 | 
				
			||||||
 | 
					            name,
 | 
				
			||||||
 | 
					            value
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -18,46 +18,38 @@ pub async fn count(msg: Message, db: std::sync::Arc<Client>) {
 | 
				
			|||||||
        &[],
 | 
					        &[],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .await
 | 
					    .await
 | 
				
			||||||
    .expect("cant create a user table");
 | 
					    .expect("Can't create a user table");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for row in db
 | 
					    for row in db
 | 
				
			||||||
        .query("SELECT name, reg FROM words", &[])
 | 
					        .query("SELECT name, reg FROM words", &[])
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .expect("can't get the words to count")
 | 
					        .expect("Can't get the words to count")
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let name: &str = row.get(0);
 | 
					        let name: &str = row.get(0);
 | 
				
			||||||
        let regex: Regex = Regex::new(row.get(1)).unwrap();
 | 
					        let regex: Regex = Regex::new(row.get(1)).unwrap();
 | 
				
			||||||
        let count = regex.captures_iter(&msg.content).count();
 | 
					        let count: i32 = regex.captures_iter(&msg.content).count() as i32;
 | 
				
			||||||
        if count > 0 {
 | 
					        if count > 0 {
 | 
				
			||||||
            let query_result = db
 | 
					            let query_result = db
 | 
				
			||||||
                .query(
 | 
					                .query(
 | 
				
			||||||
                    format!("SELECT count FROM user{} where name='{}'", id, name).as_str(),
 | 
					                    format!("SELECT count FROM user{} WHERE name=$1", id).as_str(),
 | 
				
			||||||
                    &[],
 | 
					                    &[&name],
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .await
 | 
					                .await
 | 
				
			||||||
                .expect("cant select the count");
 | 
					                .expect("Can't select count");
 | 
				
			||||||
            if query_result.is_empty() {
 | 
					            if query_result.is_empty() {
 | 
				
			||||||
                db.execute(
 | 
					                db.execute(
 | 
				
			||||||
                    format!(
 | 
					                    format!("INSERT INTO user{} (name, count) values ($1, 0)", id).as_str(),
 | 
				
			||||||
                        "insert into user{} (name, count) values ('{}', 0)",
 | 
					                    &[&name],
 | 
				
			||||||
                        id, name
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    .as_str(),
 | 
					 | 
				
			||||||
                    &[],
 | 
					 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .await
 | 
					                .await
 | 
				
			||||||
                .expect("cant insert shit");
 | 
					                .expect("Can't insert count");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            db.execute(
 | 
					            db.execute(
 | 
				
			||||||
                format!(
 | 
					                format!("UPDATE user{} SET count = count + $1 WHERE name=$2", id).as_str(),
 | 
				
			||||||
                    "UPDATE user{} SET count = count + {} where name='{}'",
 | 
					                &[&count, &name],
 | 
				
			||||||
                    id, count, name
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                .as_str(),
 | 
					 | 
				
			||||||
                &[],
 | 
					 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            .await
 | 
					            .await
 | 
				
			||||||
            .expect("cant update");
 | 
					            .expect("Can't update count");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,15 +2,7 @@ mod count;
 | 
				
			|||||||
mod interactions;
 | 
					mod interactions;
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{
 | 
				
			||||||
    async_trait,
 | 
					    async_trait,
 | 
				
			||||||
    model::{
 | 
					    model::{channel::Message, event::ResumedEvent, gateway::Ready},
 | 
				
			||||||
        channel::Message,
 | 
					 | 
				
			||||||
        event::ResumedEvent,
 | 
					 | 
				
			||||||
        gateway::Ready,
 | 
					 | 
				
			||||||
        interactions::{
 | 
					 | 
				
			||||||
            ApplicationCommand, Interaction, InteractionData, InteractionResponseType,
 | 
					 | 
				
			||||||
            InteractionType,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    prelude::*,
 | 
					    prelude::*,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use tracing::info;
 | 
					use tracing::info;
 | 
				
			||||||
@@ -19,12 +11,8 @@ pub struct Handler;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[async_trait]
 | 
					#[async_trait]
 | 
				
			||||||
impl EventHandler for Handler {
 | 
					impl EventHandler for Handler {
 | 
				
			||||||
    async fn ready(&self, ctx: Context, ready: Ready) {
 | 
					    async fn ready(&self, _: Context, ready: Ready) {
 | 
				
			||||||
        info!("{} connected bhay", ready.user.name);
 | 
					        println!("{} connected bhay", ready.user.name);
 | 
				
			||||||
        let _ = ApplicationCommand::create_global_application_commands(&ctx.http, |commands| {
 | 
					 | 
				
			||||||
            commands.set_application_commands(interactions::general())
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .await;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    async fn resume(&self, _: Context, _: ResumedEvent) {
 | 
					    async fn resume(&self, _: Context, _: ResumedEvent) {
 | 
				
			||||||
        info!("how th when the");
 | 
					        info!("how th when the");
 | 
				
			||||||
@@ -37,23 +25,4 @@ impl EventHandler for Handler {
 | 
				
			|||||||
            .clone();
 | 
					            .clone();
 | 
				
			||||||
        count::count(msg, db_client).await;
 | 
					        count::count(msg, db_client).await;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
 | 
					 | 
				
			||||||
        if interaction.kind == InteractionType::ApplicationCommand {
 | 
					 | 
				
			||||||
            if let Some(InteractionData::ApplicationCommand(data)) = interaction.data.as_ref() {
 | 
					 | 
				
			||||||
                if let Err(why) = interaction
 | 
					 | 
				
			||||||
                    .create_interaction_response(&ctx.http, |response| {
 | 
					 | 
				
			||||||
                        response
 | 
					 | 
				
			||||||
                            .kind(InteractionResponseType::ChannelMessageWithSource)
 | 
					 | 
				
			||||||
                            .interaction_response_data(|message| {
 | 
					 | 
				
			||||||
                                interactions::responses(data.name.to_string(), message)
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                    })
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    println!("Cannot respond to slash command: {}", why);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								src/lib/components.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/lib/components.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					use serenity::{
 | 
				
			||||||
 | 
					    builder::{CreateComponents, CreateSelectMenu},
 | 
				
			||||||
 | 
					    model::{channel::ReactionType, interactions::message_component::ButtonStyle},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn make_range_select_menu(first: usize, last: usize) -> CreateSelectMenu {
 | 
				
			||||||
 | 
					    let mut sm = CreateSelectMenu::default();
 | 
				
			||||||
 | 
					    sm.custom_id("range")
 | 
				
			||||||
 | 
					        .placeholder("Page No")
 | 
				
			||||||
 | 
					        .options(|mut os| {
 | 
				
			||||||
 | 
					            for x in first..=last {
 | 
				
			||||||
 | 
					                os = os.create_option(|o| o.label(x).value(x));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            os
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    sm
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn make_terminal_components(terminal: &str, pages: usize) -> CreateComponents {
 | 
				
			||||||
 | 
					    let mut c = CreateComponents::default();
 | 
				
			||||||
 | 
					    c.create_action_row(|ar| {
 | 
				
			||||||
 | 
					        ar.create_button(|b| {
 | 
				
			||||||
 | 
					            b.style(ButtonStyle::Primary)
 | 
				
			||||||
 | 
					                .label("First")
 | 
				
			||||||
 | 
					                .emoji(ReactionType::Unicode("\u{23EA}".to_string()))
 | 
				
			||||||
 | 
					                .custom_id("first")
 | 
				
			||||||
 | 
					                .disabled(terminal == "first")
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .create_button(|b| {
 | 
				
			||||||
 | 
					            b.style(ButtonStyle::Primary)
 | 
				
			||||||
 | 
					                .label("Prev")
 | 
				
			||||||
 | 
					                .emoji(ReactionType::Unicode("\u{25C0}".to_string()))
 | 
				
			||||||
 | 
					                .custom_id("prev")
 | 
				
			||||||
 | 
					                .disabled(terminal == "first")
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .create_button(|b| {
 | 
				
			||||||
 | 
					            b.style(ButtonStyle::Primary)
 | 
				
			||||||
 | 
					                .label("Next")
 | 
				
			||||||
 | 
					                .emoji(ReactionType::Unicode("\u{25B6}".to_string()))
 | 
				
			||||||
 | 
					                .custom_id("next")
 | 
				
			||||||
 | 
					                .disabled(terminal == "last")
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .create_button(|b| {
 | 
				
			||||||
 | 
					            b.style(ButtonStyle::Primary)
 | 
				
			||||||
 | 
					                .label("Last")
 | 
				
			||||||
 | 
					                .emoji(ReactionType::Unicode("\u{23E9}".to_string()))
 | 
				
			||||||
 | 
					                .custom_id("last")
 | 
				
			||||||
 | 
					                .disabled(terminal == "last")
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .create_button(|b| {
 | 
				
			||||||
 | 
					            b.style(ButtonStyle::Danger)
 | 
				
			||||||
 | 
					                .label("Delete")
 | 
				
			||||||
 | 
					                .emoji(ReactionType::Unicode("\u{1F5D1}".to_string()))
 | 
				
			||||||
 | 
					                .custom_id("delete")
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if pages <= 25 {
 | 
				
			||||||
 | 
					        c.create_action_row(|ar| ar.add_select_menu(make_range_select_menu(1, pages)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								src/lib/messages.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/lib/messages.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					use serenity::model::channel::Message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait ExtractInfo {
 | 
				
			||||||
 | 
					    fn extract_text(&self, skip: usize, with_ref: bool) -> Option<String>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ExtractInfo for Message {
 | 
				
			||||||
 | 
					    fn extract_text(&self, skip: usize, with_ref: bool) -> Option<String> {
 | 
				
			||||||
 | 
					        let mut ret: String = String::from("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let raw: Vec<&str> = self.content.splitn(skip + 1, " ").collect();
 | 
				
			||||||
 | 
					        if raw.len() == skip + 1 {
 | 
				
			||||||
 | 
					            ret += raw[skip];
 | 
				
			||||||
 | 
					            ret += "\n";
 | 
				
			||||||
 | 
					        } else if raw.len() < skip {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ret += &self
 | 
				
			||||||
 | 
					            .attachments
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .map(|x| x.url.clone())
 | 
				
			||||||
 | 
					            .collect::<Vec<String>>()
 | 
				
			||||||
 | 
					            .join("\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if let Some(msg) = &self.referenced_message {
 | 
				
			||||||
 | 
					                let ref_text = msg.extract_text(0, false);
 | 
				
			||||||
 | 
					                if with_ref && !ref_text.is_none() {
 | 
				
			||||||
 | 
					                    ret += "\n";
 | 
				
			||||||
 | 
					                    ret += &ref_text.unwrap();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ret.is_empty() {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return Some(ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								src/lib/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/lib/mod.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					pub mod components;
 | 
				
			||||||
 | 
					pub mod messages;
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,8 +1,10 @@
 | 
				
			|||||||
mod commands;
 | 
					mod commands;
 | 
				
			||||||
mod handler;
 | 
					mod handler;
 | 
				
			||||||
 | 
					mod lib;
 | 
				
			||||||
use commands::count::*;
 | 
					use commands::count::*;
 | 
				
			||||||
use commands::general::*;
 | 
					use commands::general::*;
 | 
				
			||||||
use commands::minigames::*;
 | 
					use commands::minigames::*;
 | 
				
			||||||
 | 
					use commands::tags::*;
 | 
				
			||||||
use handler::Handler;
 | 
					use handler::Handler;
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{
 | 
				
			||||||
    client::bridge::gateway::ShardManager,
 | 
					    client::bridge::gateway::ShardManager,
 | 
				
			||||||
@@ -36,10 +38,13 @@ impl TypeMapKey for Database {
 | 
				
			|||||||
struct General;
 | 
					struct General;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[group]
 | 
					#[group]
 | 
				
			||||||
#[prefix = "count"]
 | 
					#[commands(count, cadd, cremove, cedit, clist)]
 | 
				
			||||||
#[commands(kitna, add, rm, change, ls)]
 | 
					 | 
				
			||||||
struct Count;
 | 
					struct Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[group]
 | 
				
			||||||
 | 
					#[commands(tag, tadd, tcopy, tremove, tedit, tlist, trandom)]
 | 
				
			||||||
 | 
					pub struct Tags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[group]
 | 
					#[group]
 | 
				
			||||||
#[commands(challenge)]
 | 
					#[commands(challenge)]
 | 
				
			||||||
struct Minigames;
 | 
					struct Minigames;
 | 
				
			||||||
@@ -82,6 +87,7 @@ async fn main() {
 | 
				
			|||||||
        .help(&MY_HELP)
 | 
					        .help(&MY_HELP)
 | 
				
			||||||
        .group(&GENERAL_GROUP)
 | 
					        .group(&GENERAL_GROUP)
 | 
				
			||||||
        .group(&COUNT_GROUP)
 | 
					        .group(&COUNT_GROUP)
 | 
				
			||||||
 | 
					        .group(&TAGS_GROUP)
 | 
				
			||||||
        .group(&MINIGAMES_GROUP);
 | 
					        .group(&MINIGAMES_GROUP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut client = Client::builder(&token)
 | 
					    let mut client = Client::builder(&token)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user