'
+ }
+}
+
+exports {
+ 'getTimestamp'
+}
+
+game 'common'
+fx_version 'adamant'
diff --git a/resources/[tools]/cc-chat-1/server/main.lua b/resources/[tools]/cc-chat-1/server/main.lua
new file mode 100644
index 000000000..efc19c82f
--- /dev/null
+++ b/resources/[tools]/cc-chat-1/server/main.lua
@@ -0,0 +1,76 @@
+local svConfig = {}
+
+-- Configuration
+ svConfig.versionChecker = true -- Version Checker
+ svConfig.supportChecker = true -- Support Checker (If you use exports, it is recommended that you leave this on)
+
+-- Script
+AddEventHandler('onResourceStart', function(resourceName)
+ updateLogFile('Resource Started')
+ if (GetCurrentResourceName() ~= resourceName) then
+ return
+ end
+ if GetCurrentResourceName() ~= 'cc-chat' and svConfig.supportChecker == true then
+ print('^6[Warning]^0 For better support, it is recommended that "'..GetCurrentResourceName().. '" be renamed to "cc-chat"')
+ end
+ if svConfig.versionChecker == true then
+ PerformHttpRequest('https://api.github.com/repos/Concept-Collective/cc-chat/releases/latest', function (err, data, headers)
+ if data == nil then
+ print('An error occurred while checking the version. Your firewall may be blocking access to "github.com". Please check your firewall settings and ensure that "github.com" is allowed to establish connections.')
+ return
+ end
+ local data = json.decode(data)
+ if data.tag_name ~= 'v'..GetResourceMetadata(GetCurrentResourceName(), 'version', 0) then
+ print('\n^1================^0')
+ print('^1CC Chat ('..GetCurrentResourceName()..') is outdated!^0')
+ print('Current version: (^1v'..GetResourceMetadata(GetCurrentResourceName(), 'version', 0)..'^0)')
+ print('Latest version: (^2'..data.tag_name..'^0) '..data.html_url)
+ print('Release notes: '..data.body)
+ print('^1================^0')
+ end
+ end, 'GET', '')
+ end
+end)
+
+AddEventHandler('chatMessage', function(source, author, message)
+ local formattedMessage = author .. ': ' .. message
+ updateLogFile(formattedMessage)
+end)
+
+function updateLogFile(v)
+ if LoadResourceFile(GetCurrentResourceName(), 'chat_log.log') == nil then
+ SaveResourceFile(GetCurrentResourceName(), 'chat_log.log', '')
+ end
+ local logFile = LoadResourceFile(GetCurrentResourceName(), 'chat_log.log')
+ local logFile = logFile .. os.date("[%H:%M:%S] ") .. v .. '\n'
+ SaveResourceFile(GetCurrentResourceName(), 'chat_log.log', logFile)
+end
+
+-- Antispam System (Beta)
+local users = {}
+function checkSpam(source, message)
+ local BlockedStatus = false
+
+ -- Checks if the user has sent a message before
+ if users[source] == nil then
+ users[source] = {time = os.time()}
+ return false
+ end
+
+ -- Check if the user has sent messages too quickly
+ if os.time() - users[source].time < 2 then
+ BlockedStatus = true
+ end
+
+ -- Check if the message is a repeat of the last message
+ if message == users[source].lastMessage then
+ BlockedStatus = true
+ end
+
+ -- Update the user's information in the table
+ users[source] = {lastMessage = message, time = os.time()}
+
+ return BlockedStatus
+end
+
+exports('checkSpam', checkSpam)
\ No newline at end of file
diff --git a/resources/[tools]/cc-chat-1/theme/style.css b/resources/[tools]/cc-chat-1/theme/style.css
new file mode 100644
index 000000000..35cd57a22
--- /dev/null
+++ b/resources/[tools]/cc-chat-1/theme/style.css
@@ -0,0 +1,271 @@
+/* Font Awesome Import */
+@import url('https://use.fontawesome.com/releases/v6.4.0/css/all.css');
+
+/* Colors */
+.color-0 {color: #ecf0f1;}
+.color-1 {color: #e67e22;}
+.color-2 {color: #2ecc71;}
+.color-3 {color: #f1c40f;}
+.color-4 {color: #2980b9;}
+.color-5 {color: #3498db;}
+.color-6 {color: #9b59b6;}
+.color-8 {color: #e74c3c;}
+.color-9 {color: #c0392b;}
+
+.gameColor-w {color: #ffffff;}
+.gameColor-r {color: #ff4444;}
+.gameColor-g {color: #99cc00;}
+.gameColor-y {color: #ffbb33;}
+.gameColor-b {color: #33b5e5;}
+
+* {
+ font-family: "Segoe UI", Arial, sans-serif;
+ src: url("../BarlowCondensed.ttf");
+ margin: 0;
+ padding: 0;
+ font-size: 0.9rem;
+ background: #00000000;
+}
+
+.no-grow {
+ flex-grow: 0;
+}
+
+em {
+ font-style: normal;
+}
+
+#app {
+ font-family: 'Barlow Condensed', sans-serif;
+ --webkit-font-smoothing: antialiased;
+ --moz-osx-font-smoothing: grayscale;
+ color: #ecf0ff;
+ background-color: transparent;
+}
+
+.chat-window {
+ position: absolute;
+ top: 1.5%;
+ left: 0.8%;
+ width: 30% !important;
+ height: 29.9% !important;
+ max-width: 1000px;
+ background: #00000000 !important;
+ background-color: #00000000 !important;
+ --webkit-animation-duration: 2s;
+}
+
+.chat-messages {
+ position: relative;
+ height: 95%;
+ font-size: 1.0rem;
+ margin: 1%;
+
+ overflow-x: hidden;
+ overflow-y: hidden;
+}
+
+.chat-input {
+ font-size: 1.65vh;
+ position: absolute;
+
+ top: 2%;
+ left: 35%;
+ width: 30%;
+ max-width: 1000px;
+ box-sizing: border-box;
+}
+
+.prefix {
+ opacity: 0;
+ height: 0px;
+ width: 0px;
+}
+
+.chat-input > div.input {
+ position: relative;
+ display: flex;
+ align-items: stretch;
+ width: 100%;
+ min-height: 40px !important;
+ height: auto;
+ background-color: #24262a;
+ opacity: 85%;
+ border-radius: 14px;
+}
+
+textarea {
+ font-size: 17;
+ display: block;
+ box-sizing: border-box;
+ padding: 5px;
+ margin-right: 5px;
+ margin-bottom: 7px;
+ margin-left: 5px;
+ margin-top: 7px;
+ color: #ffffff;
+ background: #00000000 !important;
+ background-color: #00000000 !important;
+ width: 50%;
+ border-width: 0;
+ min-height: 40px !important;
+ overflow: show;
+ resize: none;
+}
+
+textarea:focus, input:focus {
+ outline: none;
+}
+
+.suggestions {
+ margin-top: 20px;
+ list-style-type: none;
+ padding: 0px;
+ padding-left: 27px;
+ font-size: 0.9rem;
+ box-sizing: border-box;
+ color: #ffffff;
+ background-color: rgba(36, 38, 42, 0.85) !important;
+ border-radius: 14px;
+ width: 100%;
+ padding-left: 0px;
+ padding: 6px;
+ padding-bottom: 3px;
+}
+
+.suggestion {
+ background-color: #17181a !important;
+ opacity: 100%;
+ border-radius: 8px;
+ padding: 7px;
+ font-weight: bold;
+}
+
+.suggestion small {
+ font-size: medium;
+ color: #989898;
+}
+
+.disabled {
+ color: #989898 !important;
+ background-color: rgba(252, 253, 254, 0) !important;
+}
+.param.disabled {
+ background: linear-gradient(45deg, rgba(224,224,224,1) 0%, rgba(161,161,161,1) 100%) !important;
+ color: #26292E !important;
+}
+
+.param {
+ background: linear-gradient(45deg, rgba(255,255,255,1) 0%, rgba(223,223,223,1) 100%);
+ color: #26292E !important;
+ padding: 1px;
+ padding-left: 5px;
+ padding-right: 5px;
+ border-radius: 2px;
+ margin-right: 5px;
+}
+
+.msg {
+ margin-bottom: 5px;
+}
+
+.multiline {
+ margin-left: 1.5rem;
+ text-indent: -1.5rem;
+ white-space: pre-line;
+}
+
+.help {
+ color: #FFFFFF;
+}
+
+.disabled {
+ color: #FFFFFF;
+}
+
+.suggestion {
+ margin-bottom: 5px;
+}
+
+h1 {
+ font-size: 13px;
+ font-weight: bolder;
+}
+
+h2 {
+ font-size: 13px;
+ font-weight: 900;
+}
+
+p {
+ font-size: 15px;
+ font-weight:650;
+ margin-bottom: 2px;
+}
+
+#notification {
+ display: flex;
+ padding: 6px;
+ background-color: rgba(0, 0, 0, 0.6) !important;
+ color: #FEFEFF;
+ border-radius: 14px;
+ max-width: 98%;
+ margin-bottom: 5px;
+ width: fit-content;
+ min-width: 15%;
+ word-wrap: break-word;
+}
+
+#color-box {
+ width: 10px;
+ float: left;
+ min-height: 100%;
+ border-radius: 8px;
+ flex-shrink:0;
+}
+
+#info {
+ margin-left: 10px;
+ width: auto;
+ max-width: 100%;
+ position: relative;
+ min-width: 85%;
+}
+
+#top-info {
+ padding-bottom: 5px;
+}
+
+#left-info {
+ float:left;
+ width:auto;
+ margin-top: 2px;
+}
+
+#right-info{
+ float:right;
+ width:50%;
+}
+
+#title {
+ float:left;
+ width: auto;
+ padding-right: 10px;
+}
+
+#sub-title {
+ float:right;
+ color: #C6C6C6;
+ padding-right: 10px;
+}
+
+#time {
+ float: right;
+ right: 5px;
+ color: #C6C6C6;
+ margin-top: 2px;
+}
+
+.noisy {
+ background-image: url(data:image/png;base64,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);
+}
\ No newline at end of file