├── .DS_Store ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── Setup.hs ├── haskell-discord-compiler.cabal ├── hie.yml ├── src ├── Main.hs └── files │ └── README.md ├── stack.yaml ├── stack.yaml.lock └── token.txt /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranon-rat/haskell-discord-compiler/31a78b8309856e7212dc52592ff6057e84238801/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-* 3 | cabal-dev 4 | *.o 5 | *.hi 6 | *.chi 7 | *.chs.h 8 | *.dyn_o 9 | *.dyn_hi 10 | .hpc 11 | .hsenv 12 | .cabal-sandbox/ 13 | cabal.sandbox.config 14 | *.prof 15 | *.aux 16 | *.hp 17 | *.eventlog 18 | .stack-work/ 19 | cabal.project.local 20 | cabal.project.local~ 21 | .HTF/ 22 | .ghc.environment.* 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright ranon-rat (c) 2021 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Author name here nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Haskell-discord-compiler](https://discord.gg/e52RFh7Cg2) 2 | A simple discord compiler that its made in haskell , I made this for fun and I tried to improve my skills in haskell. 3 | 4 | I couldn't have done this project without [discord-haskell](https://hackage.haskell.org/package/discord-haskell) 5 | ## How it looks 6 | | simple function| error| infinite loop| 7 | |--|--|--| 8 | |![img](https://media.discordapp.net/attachments/820472030474272769/857759230135762964/Screen_Shot_2021-06-24_at_18.08.10.png?width=1237&height=941)|![img](https://media.discordapp.net/attachments/820472030474272769/857762776840011786/Screen_Shot_2021-06-24_at_18.22.50.png?width=1232&height=943)|![img](https://media.discordapp.net/attachments/820472030474272769/858101201711005746/Screen_Shot_2021-06-25_at_16.47.33.png) 9 | ## List of commands 10 | | command| function| 11 | |--|--| 12 | |$help |this command is for receive help lmao| 13 | |$github |if you want to see the source code| 14 | |$server |if you want to join us| 15 | |$compile |this compile the input ant then return the output| 16 | ## How to deploy it 17 | 18 | first u need the [haskell dev kit](https://www.haskell.org/downloads/#linux-mac-freebsd) and install [stack](https://docs.haskellstack.org/en/stable/README/) then put the token in the file `token.txt` .After that you need to run the command 19 | ```bash 20 | stack run 21 | ``` 22 | 23 | 24 | ## Me after made this project 25 | ![image](https://media1.tenor.com/images/9385eb15bbb7a5d76357a1a59544b072/tenor.gif?itemid=12496470) 26 | 27 | [discord server](https://discord.gg/e52RFh7Cg2) 28 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -- 4 | -------------------------------------------------------------------------------- /haskell-discord-compiler.cabal: -------------------------------------------------------------------------------- 1 | name: haskell-discord-compiler 2 | version: 0.1.0.0 3 | -- synopsis: 4 | -- description: 5 | homepage: https://github.com/ranon-rat/haskell-discord-compiler#readme 6 | license: BSD3 7 | license-file: LICENSE 8 | author: ranon-rat 9 | maintainer: ranon-rat#0920 10 | copyright: 2021 ranon-rat 11 | category: Web 12 | build-type: Simple 13 | cabal-version: >=1.10 14 | extra-source-files: README.md 15 | 16 | executable haskell-discord-compiler 17 | hs-source-dirs: src 18 | main-is: Main.hs 19 | default-language: Haskell2010 20 | ghc-options: -threaded 21 | build-depends: base >= 4.7 && < 5 22 | , emoji == 0.1.0.2 23 | , text==1.2.4.1 24 | , mtl==2.2.2 25 | , transformers==0.5.6.2 26 | , discord-haskell==1.8.8 27 | , directory==1.3.6.0 28 | , regex-compat==0.95.2.1 29 | , process==1.6.9.0 30 | , random==1.2.0 31 | , unliftio==0.2.18 32 | , split==0.2.3.4 33 | 34 | -------------------------------------------------------------------------------- /hie.yml: -------------------------------------------------------------------------------- 1 | cradle: 2 | stack: 3 | - path: "./src/Main.hs" 4 | component: "haskell-discord-compiler:exe:haskell-discord-compiler" 5 | - path: "./Setup.hs" -------------------------------------------------------------------------------- /src/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | 3 | module Main where 4 | 5 | import Control.Concurrent (threadDelay) 6 | import Control.Monad (unless, when) 7 | import Control.Monad.IO.Class (MonadIO (liftIO)) 8 | import Data.List.Split (splitOn) 9 | import Data.Text (Text, pack, toLower, unpack) 10 | import qualified Data.Text.IO as TIO 11 | import Discord (DiscordHandler, RunDiscordOpts (discordOnEvent, discordToken), def, restCall, runDiscord) 12 | import Discord.Internal.Rest.Channel (ChannelRequest) 13 | import qualified Discord.Requests as R 14 | import Discord.Types (CreateEmbed (createEmbedAuthorName, createEmbedAuthorUrl, createEmbedDescription, createEmbedImage, createEmbedTitle), CreateEmbedImage (CreateEmbedImageUrl), Event (MessageCreate), Message (messageAuthor, messageChannel, messageId, messageText), User (userIsBot)) 15 | import System.Directory (removeFile) 16 | import System.IO (hGetContents) 17 | import System.Process (CreateProcess (std_err, std_out), StdStream (CreatePipe), cleanupProcess, createProcess, interruptProcessGroupOf, proc, terminateProcess) 18 | import System.Random (randomIO) 19 | import Text.Regex (Regex, matchRegex, mkRegex, subRegex) 20 | 21 | replaceSomeShittyStuff :: String -> String 22 | replaceSomeShittyStuff x = 23 | case matchRegex (mkRegex "(readFile |writeFile)") x of 24 | Nothing -> x 25 | Just _ -> replaceSomeShittyStuff (subRegex (mkRegex "(readFile |writeFile)") x "") 26 | 27 | find :: Eq a => [a] -> [a] -> Bool 28 | find x y = any (\a -> take (length y) (drop a x) == y) [0 .. (length x)] 29 | 30 | getCode :: String -> String 31 | getCode x = replaceSomeShittyStuff $drop (if find x "```hs" then 14 else 12) $take (length x - 3) x 32 | 33 | executeCode :: Message -> IO (ChannelRequest Message) 34 | executeCode x = do 35 | id <- randomIO :: IO Int 36 | let (nameCode, nameOut) = 37 | ( "./src/files/" ++ show (if id < 0 then id * (-1) else id) ++ ".hs", 38 | "src/files/" ++ show (if id < 0 then id * (-1) else id) ++ ".txt" 39 | ) 40 | code = replaceSomeShittyStuff $getCode $unpack $messageText x 41 | if not $null code 42 | then do 43 | writeFile nameCode (replaceSomeShittyStuff $getCode $unpack $messageText x) 44 | (_, Just outHandler, Just errHandle, ph) <- 45 | createProcess 46 | (proc "sh" ["-c", "echo main | ghci " ++ nameCode ++ " -no-global-package-db -no-user-package-db >" ++ nameOut ++ " & sleep 3;kill $!"]) 47 | { std_out = CreatePipe, 48 | std_err = CreatePipe 49 | } 50 | threadDelay $ 2 * 10 ^ 6 51 | terminateProcess ph 52 | outIO <- readFile nameOut 53 | errIO <- hGetContents errHandle 54 | d <- hGetContents outHandler 55 | print d 56 | 57 | let message = 58 | R.CreateMessageEmbed 59 | (messageChannel x) 60 | "output" 61 | $def 62 | { createEmbedAuthorName = "server", 63 | createEmbedAuthorUrl = "https://discord.gg/e52RFh7Cg2", 64 | createEmbedTitle = if not $find outIO "Failed" then "Big brain Moment" else "Error 😩", 65 | createEmbedDescription = 66 | pack $ 67 | "```" 68 | ++ ( if not $find outIO "Failed" 69 | then take 500 (drop 179 $ take (length outIO -21) outIO) 70 | else "hs\n" ++ take 500 errIO ++ "\n" 71 | ) 72 | ++ "```", 73 | createEmbedImage = 74 | if find outIO "Failed" 75 | then Just $ CreateEmbedImageUrl "https://media1.tenor.com/images/039d5fa4895c07d58b8c88e69847cf16/tenor.gif?itemid=17634321" 76 | else Just $ CreateEmbedImageUrl "https://i0.wp.com/media1.tenor.com/images/a7215e2bf39482df8bb694f132af5c78/tenor.gif?itemid=16327782?resize=91,91" 77 | } 78 | mapM_ removeFile [nameCode, nameOut] 79 | return message 80 | else return . R.CreateMessageEmbed (messageChannel x) "error" $def {createEmbedTitle = "Missing arguments", createEmbedImage = Just $ CreateEmbedImageUrl "https://media.discordapp.net/attachments/820472030474272769/858103586511519744/Screen_Shot_2021-06-25_at_16.57.05.png"} 81 | 82 | runBot :: Text -> IO () 83 | runBot token = do 84 | userFacingError <- runDiscord $ def {discordToken = token, discordOnEvent = eventHandler} 85 | TIO.putStrLn userFacingError 86 | 87 | eventHandler :: Event -> DiscordHandler () 88 | eventHandler event = 89 | case event of 90 | MessageCreate m -> when (not (userIsBot (messageAuthor m)) && take 1 (unpack $messageText m) == "$") $ do 91 | case head $splitOn " " $unpack $messageText m of 92 | "$compile" -> do 93 | _ <- restCall (R.CreateReaction (messageChannel m, messageId m) "eyes") 94 | messReq <- liftIO (executeCode m) 95 | _ <- restCall messReq 96 | pure () 97 | "$server" -> do 98 | _ <- restCall (R.CreateMessage (messageChannel m) "https://discord.gg/e52RFh7Cg2") 99 | _ <- restCall (R.CreateReaction (messageChannel m, messageId m) "hearts") 100 | pure () 101 | "$help" -> do 102 | _ <- 103 | restCall 104 | ( R.CreateMessageEmbed 105 | (messageChannel m) 106 | "" 107 | $def 108 | { createEmbedAuthorName = "server", 109 | createEmbedAuthorUrl = "https://discord.gg/e52RFh7Cg2", 110 | createEmbedTitle = "list of commands", 111 | createEmbedDescription = "```md\n- $help *this command is for receive help lmao*\n- $github *if you want to see the source code*\n- $server *if you want to join us*\n- $compile *this compile the input ant then return the output* ```", 112 | createEmbedImage = Just $ CreateEmbedImageUrl "https://media.discordapp.net/attachments/820472030474272769/858103586511519744/Screen_Shot_2021-06-25_at_16.57.05.png" 113 | } 114 | ) 115 | pure () 116 | "$github" -> do 117 | _ <- restCall (R.CreateReaction (messageChannel m, messageId m) "hearts") 118 | _ <- restCall (R.CreateMessage (messageChannel m) "https://github.com/ranon-rat/haskell-discord-compiler") 119 | pure () 120 | _ -> pure () 121 | _ -> pure () 122 | 123 | main :: IO () 124 | main = do 125 | putStrLn "the bot is running" 126 | 127 | token <- readFile "token.txt" 128 | runBot $ pack token -------------------------------------------------------------------------------- /src/files/README.md: -------------------------------------------------------------------------------- 1 | this is for not ignore this folder 2 | 3 | here's why 4 | [why](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: 2 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/0.yaml 3 | 4 | 5 | extra-deps: 6 | - emoji-0.1.0.2 7 | - discord-haskell-1.8.8 8 | - regex-compat-0.95.2.1 9 | - process-1.6.9.0 10 | - random-1.2.0 11 | - transformers-0.5.6.2 12 | 13 | 14 | #- Cabal-3.4.0.0@sha256:74ca2bc93297dc20b291c8dc721055278aa4a7942b0b5aca86766d407e3cbe5f,30533 15 | packages: 16 | - . -------------------------------------------------------------------------------- /stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/lock_files 5 | 6 | snapshots: 7 | - original: 8 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/0.yaml 9 | completed: 10 | sha256: c632012da648385b9fa3c29f4e0afd56ead299f1c5528ee789058be410e883c0 11 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/0.yaml 12 | size: 585393 13 | packages: 14 | - original: 15 | hackage: emoji-0.1.0.2 16 | completed: 17 | pantry-tree: 18 | sha256: dd9ea90a631342e5db0fc21331ade4d563a685e9125d5a3989eefa8e1b96c6c6 19 | size: 437 20 | hackage: emoji-0.1.0.2@sha256:d995572a5c7dcd28f98eb15c6e387a7b3bda1ac2477ab0d9dba8580d5d7b161f,1273 21 | - original: 22 | hackage: discord-haskell-1.8.8 23 | completed: 24 | pantry-tree: 25 | sha256: cbf772087fdc87d74d48514bf1996d9656002542be75bad306be5a028a937d7b 26 | size: 2107 27 | hackage: discord-haskell-1.8.8@sha256:647bf08777aebcc8d5eacdb729906b2b05f7832c3b767d87059ef13462ff8875,3562 28 | - original: 29 | hackage: regex-compat-0.95.2.1 30 | completed: 31 | pantry-tree: 32 | sha256: ef1a838d356fb267a04adbf12ea2cf723fca75bad4bfdb59d33718362c18370f 33 | size: 262 34 | hackage: regex-compat-0.95.2.1@sha256:be75931c482beeb8ecaec0b9a282aa3701762dbec40bb92ff274998b41dc153b,1726 35 | - original: 36 | hackage: process-1.6.9.0 37 | completed: 38 | pantry-tree: 39 | sha256: 9d21df864535dcc65e11fd108c4678fdadf2d53bb9ffd1fda142369c797f31c1 40 | size: 1211 41 | hackage: process-1.6.9.0@sha256:372de796fea9d40e6d02269d5df466c9b8d641f145fad3c1add59db7baeea19e,2576 42 | - original: 43 | hackage: random-1.2.0 44 | completed: 45 | pantry-tree: 46 | sha256: 92b5a834ba603ee4d006968a75847f4fd93a566b8a96e1b463b8229f8ce9961d 47 | size: 1259 48 | hackage: random-1.2.0@sha256:30d72df4cc1d2fe2d445c88f0ee9d21965af7ce86660c43a6c32a6a1d90d51c9,6094 49 | - original: 50 | hackage: transformers-0.5.6.2 51 | completed: 52 | pantry-tree: 53 | sha256: c79246ba7d61392c2f214376fed3c2a05e4b2649b93ec2c849a86493f278ace0 54 | size: 2512 55 | hackage: transformers-0.5.6.2@sha256:6c959d14430f4deffb99579ba019de07c3d852a2122b6f449344386c7d75ff1d,3172 56 | -------------------------------------------------------------------------------- /token.txt: -------------------------------------------------------------------------------- 1 | token here please 2 | --------------------------------------------------------------------------------