diff --git a/bun.lock b/bun.lock
index 17f5d6c..2fae865 100644
--- a/bun.lock
+++ b/bun.lock
@@ -20,9 +20,12 @@
"@types/lodash": "^4.17.20",
"@types/qrcode-terminal": "^0.12.2",
"add": "^2.0.6",
+ "colors": "^1.4.0",
"elysia": "^1.4.11",
+ "form-data": "^4.0.4",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
+ "node-fetch": "^3.3.2",
"qrcode-terminal": "^0.12.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
@@ -144,6 +147,8 @@
"async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
+ "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
+
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
@@ -170,6 +175,8 @@
"c12": ["c12@3.1.0", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^16.6.1", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="],
+ "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
+
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
"chainsaw": ["chainsaw@0.1.0", "", { "dependencies": { "traverse": ">=0.3.0 <0.4" } }, "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ=="],
@@ -182,6 +189,10 @@
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
+ "colors": ["colors@1.4.0", "", {}, "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="],
+
+ "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
+
"compress-commons": ["compress-commons@4.1.2", "", { "dependencies": { "buffer-crc32": "^0.2.13", "crc32-stream": "^4.0.2", "normalize-path": "^3.0.0", "readable-stream": "^3.6.0" } }, "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg=="],
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
@@ -204,12 +215,16 @@
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+ "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"deepmerge-ts": ["deepmerge-ts@7.1.5", "", {}, "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw=="],
"defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
+ "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
+
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
"destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="],
@@ -224,6 +239,8 @@
"dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
+ "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
+
"duplexer2": ["duplexer2@0.1.4", "", { "dependencies": { "readable-stream": "^2.0.2" } }, "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA=="],
"effect": ["effect@3.16.12", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg=="],
@@ -234,6 +251,14 @@
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
+ "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
+
+ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
+
+ "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
+
+ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
+
"exact-mirror": ["exact-mirror@0.2.2", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-CrGe+4QzHZlnrXZVlo/WbUZ4qQZq8C0uATQVGVgXIrNXgHDBBNFD1VRfssRA2C9t3RYvh3MadZSdg2Wy7HBoQA=="],
"exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="],
@@ -248,12 +273,18 @@
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+ "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
+
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
"file-type": ["file-type@21.0.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="],
"fluent-ffmpeg": ["fluent-ffmpeg@2.1.3", "", { "dependencies": { "async": "^0.2.9", "which": "^1.1.1" } }, "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q=="],
+ "form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
+
+ "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
+
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
"fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="],
@@ -262,16 +293,30 @@
"fstream": ["fstream@1.0.12", "", { "dependencies": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" } }, "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg=="],
+ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
+
+ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
+
"get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
+ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
+
"get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
"giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="],
"glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
+ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
+
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+ "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
+
+ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
+
+ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
+
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
"https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
@@ -316,8 +361,14 @@
"marked": ["marked@14.0.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ=="],
+ "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
+
"mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
+ "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
+
+ "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
+
"minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
"mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
@@ -330,7 +381,9 @@
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
- "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
+ "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
+
+ "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
"node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
@@ -500,6 +553,8 @@
"uuid": ["uuid@13.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="],
+ "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
+
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
"whatsapp-web.js": ["whatsapp-web.js@1.34.1", "", { "dependencies": { "@pedroslopez/moduleraid": "^5.0.2", "fluent-ffmpeg": "2.1.3", "mime": "^3.0.0", "node-fetch": "^2.6.9", "node-webpmux": "3.1.7", "puppeteer": "^18.2.1" }, "optionalDependencies": { "archiver": "^5.3.1", "fs-extra": "^10.1.0", "unzipper": "^0.10.11" } }, "sha512-IInGEg+F8wB9M+c61KXGZ4bpwq24ew9EgsyMYxUZ/4CQ8GW/afsGseQO4FZriQ16qpu14pFovsD6YrEYxRbyLw=="],
@@ -550,6 +605,8 @@
"unzipper/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
+ "whatsapp-web.js/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
+
"zip-stream/archiver-utils": ["archiver-utils@3.0.4", "", { "dependencies": { "glob": "^7.2.3", "graceful-fs": "^4.2.0", "lazystream": "^1.0.0", "lodash.defaults": "^4.2.0", "lodash.difference": "^4.5.0", "lodash.flatten": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", "readable-stream": "^3.6.0" } }, "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw=="],
"@scalar/themes/@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="],
diff --git a/downloads/ jenna ai chat Chatflow.json b/downloads/ jenna ai chat Chatflow.json
new file mode 100644
index 0000000..fc93edb
--- /dev/null
+++ b/downloads/ jenna ai chat Chatflow.json
@@ -0,0 +1,514 @@
+{
+ "nodes": [
+ {
+ "id": "llmChain_0",
+ "position": {
+ "x": 829.035635359116,
+ "y": 344.314364640884
+ },
+ "type": "customNode",
+ "data": {
+ "id": "llmChain_0",
+ "label": "LLM Chain",
+ "version": 3,
+ "name": "llmChain",
+ "type": "LLMChain",
+ "baseClasses": [
+ "LLMChain",
+ "BaseChain",
+ "Runnable"
+ ],
+ "category": "Chains",
+ "description": "Chain to run queries against LLMs",
+ "inputParams": [
+ {
+ "label": "Chain Name",
+ "name": "chainName",
+ "type": "string",
+ "placeholder": "Name Your Chain",
+ "optional": true,
+ "id": "llmChain_0-input-chainName-string",
+ "display": true
+ }
+ ],
+ "inputAnchors": [
+ {
+ "label": "Language Model",
+ "name": "model",
+ "type": "BaseLanguageModel",
+ "id": "llmChain_0-input-model-BaseLanguageModel",
+ "display": true
+ },
+ {
+ "label": "Prompt",
+ "name": "prompt",
+ "type": "BasePromptTemplate",
+ "id": "llmChain_0-input-prompt-BasePromptTemplate",
+ "display": true
+ },
+ {
+ "label": "Output Parser",
+ "name": "outputParser",
+ "type": "BaseLLMOutputParser",
+ "optional": true,
+ "id": "llmChain_0-input-outputParser-BaseLLMOutputParser",
+ "display": true
+ },
+ {
+ "label": "Input Moderation",
+ "description": "Detect text that could generate harmful output and prevent it from being sent to the language model",
+ "name": "inputModeration",
+ "type": "Moderation",
+ "optional": true,
+ "list": true,
+ "id": "llmChain_0-input-inputModeration-Moderation",
+ "display": true
+ }
+ ],
+ "inputs": {
+ "model": "{{chatOpenAI_0.data.instance}}",
+ "prompt": "{{promptTemplate_0.data.instance}}",
+ "outputParser": "",
+ "inputModeration": "",
+ "chainName": ""
+ },
+ "outputAnchors": [
+ {
+ "name": "output",
+ "label": "Output",
+ "type": "options",
+ "description": "",
+ "options": [
+ {
+ "id": "llmChain_0-output-llmChain-LLMChain|BaseChain|Runnable",
+ "name": "llmChain",
+ "label": "LLM Chain",
+ "description": "",
+ "type": "LLMChain | BaseChain | Runnable"
+ },
+ {
+ "id": "llmChain_0-output-outputPrediction-string|json",
+ "name": "outputPrediction",
+ "label": "Output Prediction",
+ "description": "",
+ "type": "string | json"
+ }
+ ],
+ "default": "llmChain"
+ }
+ ],
+ "outputs": {
+ "output": "llmChain"
+ },
+ "selected": false
+ },
+ "width": 300,
+ "height": 514,
+ "selected": false,
+ "positionAbsolute": {
+ "x": 829.035635359116,
+ "y": 344.314364640884
+ },
+ "dragging": false
+ },
+ {
+ "id": "chatOpenAI_0",
+ "position": {
+ "x": 357.9495996101249,
+ "y": -208.05581727949718
+ },
+ "type": "customNode",
+ "data": {
+ "id": "chatOpenAI_0",
+ "label": "ChatOpenAI",
+ "version": 8.3,
+ "name": "chatOpenAI",
+ "type": "ChatOpenAI",
+ "baseClasses": [
+ "ChatOpenAI",
+ "BaseChatOpenAI",
+ "BaseChatModel",
+ "BaseLanguageModel",
+ "Runnable"
+ ],
+ "category": "Chat Models",
+ "description": "Wrapper around OpenAI large language models that use the Chat endpoint",
+ "inputParams": [
+ {
+ "label": "Connect Credential",
+ "name": "credential",
+ "type": "credential",
+ "credentialNames": [
+ "openAIApi"
+ ],
+ "id": "chatOpenAI_0-input-credential-credential",
+ "display": true
+ },
+ {
+ "label": "Model Name",
+ "name": "modelName",
+ "type": "asyncOptions",
+ "loadMethod": "listModels",
+ "default": "gpt-4o-mini",
+ "id": "chatOpenAI_0-input-modelName-asyncOptions",
+ "display": true
+ },
+ {
+ "label": "Temperature",
+ "name": "temperature",
+ "type": "number",
+ "step": 0.1,
+ "default": 0.9,
+ "optional": true,
+ "id": "chatOpenAI_0-input-temperature-number",
+ "display": true
+ },
+ {
+ "label": "Streaming",
+ "name": "streaming",
+ "type": "boolean",
+ "default": true,
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-streaming-boolean",
+ "display": true
+ },
+ {
+ "label": "Max Tokens",
+ "name": "maxTokens",
+ "type": "number",
+ "step": 1,
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-maxTokens-number",
+ "display": true
+ },
+ {
+ "label": "Top Probability",
+ "name": "topP",
+ "type": "number",
+ "step": 0.1,
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-topP-number",
+ "display": true
+ },
+ {
+ "label": "Frequency Penalty",
+ "name": "frequencyPenalty",
+ "type": "number",
+ "step": 0.1,
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-frequencyPenalty-number",
+ "display": true
+ },
+ {
+ "label": "Presence Penalty",
+ "name": "presencePenalty",
+ "type": "number",
+ "step": 0.1,
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-presencePenalty-number",
+ "display": true
+ },
+ {
+ "label": "Timeout",
+ "name": "timeout",
+ "type": "number",
+ "step": 1,
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-timeout-number",
+ "display": true
+ },
+ {
+ "label": "Strict Tool Calling",
+ "name": "strictToolCalling",
+ "type": "boolean",
+ "description": "Whether the model supports the `strict` argument when passing in tools. If not specified, the `strict` argument will not be passed to OpenAI.",
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-strictToolCalling-boolean",
+ "display": true
+ },
+ {
+ "label": "Stop Sequence",
+ "name": "stopSequence",
+ "type": "string",
+ "rows": 4,
+ "optional": true,
+ "description": "List of stop words to use when generating. Use comma to separate multiple stop words.",
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-stopSequence-string",
+ "display": true
+ },
+ {
+ "label": "BasePath",
+ "name": "basepath",
+ "type": "string",
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-basepath-string",
+ "display": true
+ },
+ {
+ "label": "Proxy Url",
+ "name": "proxyUrl",
+ "type": "string",
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-proxyUrl-string",
+ "display": true
+ },
+ {
+ "label": "BaseOptions",
+ "name": "baseOptions",
+ "type": "json",
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-baseOptions-json",
+ "display": true
+ },
+ {
+ "label": "Allow Image Uploads",
+ "name": "allowImageUploads",
+ "type": "boolean",
+ "description": "Allow image input. Refer to the docs for more details.",
+ "default": false,
+ "optional": true,
+ "id": "chatOpenAI_0-input-allowImageUploads-boolean",
+ "display": true
+ },
+ {
+ "label": "Image Resolution",
+ "description": "This parameter controls the resolution in which the model views the image.",
+ "name": "imageResolution",
+ "type": "options",
+ "options": [
+ {
+ "label": "Low",
+ "name": "low"
+ },
+ {
+ "label": "High",
+ "name": "high"
+ },
+ {
+ "label": "Auto",
+ "name": "auto"
+ }
+ ],
+ "default": "low",
+ "optional": false,
+ "show": {
+ "allowImageUploads": true
+ },
+ "id": "chatOpenAI_0-input-imageResolution-options",
+ "display": false
+ },
+ {
+ "label": "Reasoning",
+ "description": "Whether the model supports reasoning. Only applicable for reasoning models.",
+ "name": "reasoning",
+ "type": "boolean",
+ "default": false,
+ "optional": true,
+ "additionalParams": true,
+ "id": "chatOpenAI_0-input-reasoning-boolean",
+ "display": true
+ },
+ {
+ "label": "Reasoning Effort",
+ "description": "Constrains effort on reasoning for reasoning models",
+ "name": "reasoningEffort",
+ "type": "options",
+ "options": [
+ {
+ "label": "Low",
+ "name": "low"
+ },
+ {
+ "label": "Medium",
+ "name": "medium"
+ },
+ {
+ "label": "High",
+ "name": "high"
+ }
+ ],
+ "additionalParams": true,
+ "show": {
+ "reasoning": true
+ },
+ "id": "chatOpenAI_0-input-reasoningEffort-options",
+ "display": false
+ },
+ {
+ "label": "Reasoning Summary",
+ "description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process",
+ "name": "reasoningSummary",
+ "type": "options",
+ "options": [
+ {
+ "label": "Auto",
+ "name": "auto"
+ },
+ {
+ "label": "Concise",
+ "name": "concise"
+ },
+ {
+ "label": "Detailed",
+ "name": "detailed"
+ }
+ ],
+ "additionalParams": true,
+ "show": {
+ "reasoning": true
+ },
+ "id": "chatOpenAI_0-input-reasoningSummary-options",
+ "display": false
+ }
+ ],
+ "inputAnchors": [
+ {
+ "label": "Cache",
+ "name": "cache",
+ "type": "BaseCache",
+ "optional": true,
+ "id": "chatOpenAI_0-input-cache-BaseCache",
+ "display": true
+ }
+ ],
+ "inputs": {
+ "cache": "",
+ "modelName": "gpt-4o-mini",
+ "temperature": 0.9,
+ "streaming": true,
+ "maxTokens": "",
+ "topP": "",
+ "frequencyPenalty": "",
+ "presencePenalty": "",
+ "timeout": "",
+ "strictToolCalling": "",
+ "stopSequence": "",
+ "basepath": "",
+ "proxyUrl": "",
+ "baseOptions": "",
+ "allowImageUploads": "",
+ "imageResolution": "low",
+ "reasoning": "",
+ "reasoningEffort": "",
+ "reasoningSummary": ""
+ },
+ "outputAnchors": [
+ {
+ "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable",
+ "name": "chatOpenAI",
+ "label": "ChatOpenAI",
+ "description": "Wrapper around OpenAI large language models that use the Chat endpoint",
+ "type": "ChatOpenAI | BaseChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable"
+ }
+ ],
+ "outputs": {},
+ "selected": false
+ },
+ "width": 300,
+ "height": 676,
+ "selected": false,
+ "positionAbsolute": {
+ "x": 357.9495996101249,
+ "y": -208.05581727949718
+ },
+ "dragging": false
+ },
+ {
+ "id": "promptTemplate_0",
+ "position": {
+ "x": 355.34464051183033,
+ "y": 518.8403272698386
+ },
+ "type": "customNode",
+ "data": {
+ "id": "promptTemplate_0",
+ "label": "Prompt Template",
+ "version": 1,
+ "name": "promptTemplate",
+ "type": "PromptTemplate",
+ "baseClasses": [
+ "PromptTemplate",
+ "BaseStringPromptTemplate",
+ "BasePromptTemplate",
+ "Runnable"
+ ],
+ "category": "Prompts",
+ "description": "Schema to represent a basic prompt for an LLM",
+ "inputParams": [
+ {
+ "label": "Template",
+ "name": "template",
+ "type": "string",
+ "rows": 4,
+ "placeholder": "What is a good name for a company that makes {product}?",
+ "id": "promptTemplate_0-input-template-string",
+ "display": true
+ },
+ {
+ "label": "Format Prompt Values",
+ "name": "promptValues",
+ "type": "json",
+ "optional": true,
+ "acceptVariable": true,
+ "list": true,
+ "id": "promptTemplate_0-input-promptValues-json",
+ "display": true
+ }
+ ],
+ "inputAnchors": [],
+ "inputs": {
+ "template": "# 🤖 Persona AI: Sahabat Percakapan Mendalam\n\n## Karakter Utama\n- Ramah, hangat, dan selalu membuat orang merasa nyaman.\n- Penasaran secara alami, suka bertanya balik untuk menjaga percakapan tetap hidup.\n- Senang mengajak orang berbagi cerita, pengalaman, dan pemikiran mendalam.\n- Tidak terburu-buru; menghargai jeda, detail, dan refleksi dari lawan bicara.\n\n## Gaya Bicara\n- Menggunakan bahasa sehari-hari yang mudah dimengerti.\n- Memberi kesan manusiawi, penuh empati, tanpa terdengar kaku.\n- Kadang menyelipkan humor ringan atau pertanyaan reflektif.\n- Lebih suka bertanya *“Kenapa menurutmu begitu?”* daripada hanya memberi jawaban singkat.\n\n## Topik Favorit\n- Pemikiran mendalam tentang kehidupan, mimpi, dan tujuan.\n- Teknologi, ide-ide baru, dan bagaimana itu memengaruhi manusia.\n- Cerita sehari-hari, pengalaman pribadi, dan hal-hal sederhana yang punya makna.\n- Diskusi terbuka tentang apa pun yang membuat orang berpikir lebih jauh.\n\n## Pola Interaksi\n1. **Membuka dengan keakraban**: menyapa dengan hangat dan membuat suasana santai. \n2. **Menggali lebih jauh**: menanyakan pendapat, alasan, atau cerita di balik jawaban. \n3. **Membangun koneksi**: mengaitkan topik dengan hal yang lebih personal atau universal. \n4. **Memancing refleksi**: memberi pertanyaan lanjutan yang mengundang renungan atau cerita tambahan. \n\n## Contoh Gaya Percakapan\n- \"Itu menarik banget, bisa ceritain lebih detail kenapa menurutmu begitu?\" \n- \"Aku penasaran, kalau situasi itu terjadi padamu, apa yang akan kamu lakukan?\" \n- \"Wah, itu kedengarannya punya makna besar buatmu. Apa ada pengalaman tertentu yang bikin kamu berpikir begitu?\" \n- \"Hmm, aku jadi kepikiran... gimana kalau kita lihat dari sudut pandang yang berbeda?\" \n\n---\n✨ Persona ini ditujukan untuk membuat AI terasa **akrab, reflektif, dan bikin percakapan selalu hidup**, bukan sekadar menjawab.\n\n{text}\n",
+ "promptValues": "{\"text\":\"{{question}}\"}"
+ },
+ "outputAnchors": [
+ {
+ "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable",
+ "name": "promptTemplate",
+ "label": "PromptTemplate",
+ "description": "Schema to represent a basic prompt for an LLM",
+ "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate | Runnable"
+ }
+ ],
+ "outputs": {},
+ "selected": false
+ },
+ "width": 300,
+ "height": 519,
+ "selected": false,
+ "positionAbsolute": {
+ "x": 355.34464051183033,
+ "y": 518.8403272698386
+ },
+ "dragging": false
+ }
+ ],
+ "edges": [
+ {
+ "source": "chatOpenAI_0",
+ "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable",
+ "target": "llmChain_0",
+ "targetHandle": "llmChain_0-input-model-BaseLanguageModel",
+ "type": "buttonedge",
+ "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_0-llmChain_0-input-model-BaseLanguageModel"
+ },
+ {
+ "source": "promptTemplate_0",
+ "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable",
+ "target": "llmChain_0",
+ "targetHandle": "llmChain_0-input-prompt-BasePromptTemplate",
+ "type": "buttonedge",
+ "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/downloads/13fc6a9d-b915-4693-9cf0-ffb51897b015.pdf b/downloads/13fc6a9d-b915-4693-9cf0-ffb51897b015.pdf
new file mode 100644
index 0000000..986ab78
Binary files /dev/null and b/downloads/13fc6a9d-b915-4693-9cf0-ffb51897b015.pdf differ
diff --git a/downloads/Apakah-Itu-Pendidikan.jpg b/downloads/Apakah-Itu-Pendidikan.jpg
new file mode 100644
index 0000000..4bfe549
Binary files /dev/null and b/downloads/Apakah-Itu-Pendidikan.jpg differ
diff --git a/downloads/Arief Nasuha Nasution.pdf b/downloads/Arief Nasuha Nasution.pdf
new file mode 100644
index 0000000..db3d70f
Binary files /dev/null and b/downloads/Arief Nasuha Nasution.pdf differ
diff --git a/downloads/BalesOtomatis.id – Analisis Sistem Otomatisasi WhatsApp Marketing.pdf b/downloads/BalesOtomatis.id – Analisis Sistem Otomatisasi WhatsApp Marketing.pdf
new file mode 100644
index 0000000..2f8908a
Binary files /dev/null and b/downloads/BalesOtomatis.id – Analisis Sistem Otomatisasi WhatsApp Marketing.pdf differ
diff --git a/downloads/Desa Darmasaba-Akta Kelahiran.pdf b/downloads/Desa Darmasaba-Akta Kelahiran.pdf
new file mode 100644
index 0000000..01710d4
Binary files /dev/null and b/downloads/Desa Darmasaba-Akta Kelahiran.pdf differ
diff --git a/downloads/arif n nasution.pdf b/downloads/arif n nasution.pdf
new file mode 100644
index 0000000..96a5ea1
Binary files /dev/null and b/downloads/arif n nasution.pdf differ
diff --git a/downloads/billing-server-20-06-2024.pdf b/downloads/billing-server-20-06-2024.pdf
new file mode 100644
index 0000000..66cd6a6
Binary files /dev/null and b/downloads/billing-server-20-06-2024.pdf differ
diff --git a/downloads/buku-saku-lele-bioflok_revisi-_FINAL_compressed.pdf b/downloads/buku-saku-lele-bioflok_revisi-_FINAL_compressed.pdf
new file mode 100644
index 0000000..77d2724
Binary files /dev/null and b/downloads/buku-saku-lele-bioflok_revisi-_FINAL_compressed.pdf differ
diff --git a/downloads/darmasaba.txt b/downloads/darmasaba.txt
new file mode 100644
index 0000000..f6c8593
--- /dev/null
+++ b/downloads/darmasaba.txt
@@ -0,0 +1,3709 @@
+```yaml
+openapi: 3.0.3
+info:
+ title: Desa+ Mobile API
+ description: API untuk aplikasi mobile Desa+ (berbasis kode client Axios).
+ version: 1.0.0
+ contact:
+ name: API Support
+ email: support@desa-plus.com
+
+servers:
+ - url: https://staging-darmasaba.wibudev.com/api
+ description: Production server
+
+components:
+ securitySchemes:
+ bearerAuth:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+
+ schemas:
+ # Common Schemas
+ User:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ phone:
+ type: string
+ required:
+ - id
+
+ Error:
+ type: object
+ properties:
+ message:
+ type: string
+ status:
+ type: integer
+
+ # Auth
+ PhoneLoginBody:
+ type: object
+ properties:
+ phone:
+ type: string
+ required:
+ - phone
+
+ OtpBody:
+ type: object
+ properties:
+ phone:
+ type: string
+ otp:
+ type: integer
+ required:
+ - phone
+ - otp
+
+ # Banner
+ Banner:
+ type: object
+ properties:
+ id:
+ type: string
+ title:
+ type: string
+ image:
+ type: string
+ user:
+ type: string
+ required:
+ - id
+
+ # Group
+ Group:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ user:
+ type: string
+ isActive:
+ type: boolean
+ required:
+ - id
+ - name
+
+ GroupCreateBody:
+ type: object
+ properties:
+ user:
+ type: string
+ name:
+ type: string
+ required:
+ - user
+ - name
+
+ # Position
+ Position:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ idGroup:
+ type: string
+ user:
+ type: string
+ isActive:
+ type: boolean
+ required:
+ - id
+ - name
+
+ PositionCreateBody:
+ type: object
+ properties:
+ user:
+ type: string
+ name:
+ type: string
+ idGroup:
+ type: string
+ required:
+ - user
+ - name
+ - idGroup
+
+ # User Management
+ UserCreateBody:
+ type: object
+ properties:
+ name:
+ type: string
+ email:
+ type: string
+ photo:
+ type: string
+ required:
+ - name
+
+ # Discussion General
+ DiscussionGeneral:
+ type: object
+ properties:
+ id:
+ type: string
+ title:
+ type: string
+ desc:
+ type: string
+ user:
+ type: string
+ status:
+ type: integer
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ required:
+ - id
+ - title
+
+ DiscussionGeneralCreateBody:
+ type: object
+ properties:
+ idGroup:
+ type: string
+ title:
+ type: string
+ desc:
+ type: string
+ user:
+ type: string
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ required:
+ - idGroup
+ - title
+ - desc
+ - user
+
+ DiscussionGeneralCommentBody:
+ type: object
+ properties:
+ desc:
+ type: string
+ user:
+ type: string
+ required:
+ - desc
+ - user
+
+ # Announcement
+ Announcement:
+ type: object
+ properties:
+ id:
+ type: string
+ title:
+ type: string
+ desc:
+ type: string
+ user:
+ type: string
+ groups:
+ type: array
+ items:
+ type: string
+ required:
+ - id
+ - title
+
+ AnnouncementCreateBody:
+ type: object
+ properties:
+ title:
+ type: string
+ desc:
+ type: string
+ user:
+ type: string
+ groups:
+ type: array
+ items:
+ type: string
+ required:
+ - title
+ - desc
+ - user
+ - groups
+
+ # Project
+ Project:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ user:
+ type: string
+ status:
+ type: integer
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ required:
+ - id
+ - name
+
+ ProjectCreateBody:
+ type: object
+ properties:
+ name:
+ type: string
+ description:
+ type: string
+ required:
+ - name
+
+ ProjectTaskCreateBody:
+ type: object
+ properties:
+ name:
+ type: string
+ dateStart:
+ type: string
+ dateEnd:
+ type: string
+ user:
+ type: string
+ dataDetail:
+ type: array
+ items:
+ type: object
+ required:
+ - name
+ - dateStart
+ - dateEnd
+ - user
+
+ ProjectUpdateStatusBody:
+ type: object
+ properties:
+ user:
+ type: string
+ status:
+ type: integer
+ idProject:
+ type: string
+ required:
+ - user
+ - status
+ - idProject
+
+ # Division
+ Division:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ desc:
+ type: string
+ user:
+ type: string
+ isActive:
+ type: boolean
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ required:
+ - id
+ - name
+
+ DivisionCreateBody:
+ type: object
+ properties:
+ data:
+ type: object
+ properties:
+ idGroup:
+ type: string
+ name:
+ type: string
+ desc:
+ type: string
+ required:
+ - idGroup
+ - name
+ - desc
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ admin:
+ type: array
+ items:
+ type: string
+ user:
+ type: string
+ required:
+ - data
+ - member
+ - admin
+ - user
+
+ DivisionMemberBody:
+ type: object
+ properties:
+ user:
+ type: string
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ required:
+ - user
+ - member
+
+ # Discussion
+ Discussion:
+ type: object
+ properties:
+ id:
+ type: string
+ desc:
+ type: string
+ user:
+ type: string
+ idDivision:
+ type: string
+ active:
+ type: boolean
+ status:
+ type: integer
+ required:
+ - id
+ - desc
+
+ DiscussionCreateBody:
+ type: object
+ properties:
+ user:
+ type: string
+ desc:
+ type: string
+ idDivision:
+ type: string
+ required:
+ - user
+ - desc
+ - idDivision
+
+ DiscussionCommentBody:
+ type: object
+ properties:
+ user:
+ type: string
+ comment:
+ type: string
+ required:
+ - user
+ - comment
+
+ DiscussionEditBody:
+ type: object
+ properties:
+ user:
+ type: string
+ desc:
+ type: string
+ required:
+ - user
+ - desc
+
+ # Calendar
+ Calendar:
+ type: object
+ properties:
+ id:
+ type: string
+ title:
+ type: string
+ desc:
+ type: string
+ timeStart:
+ type: string
+ timeEnd:
+ type: string
+ dateStart:
+ type: string
+ repeatEventTyper:
+ type: string
+ repeatValue:
+ type: string
+ linkMeet:
+ type: string
+ idDivision:
+ type: string
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ user:
+ type: string
+ required:
+ - id
+ - title
+ - desc
+ - timeStart
+ - timeEnd
+ - dateStart
+ - idDivision
+ - user
+
+ CalendarCreateBody:
+ type: object
+ properties:
+ idDivision:
+ type: string
+ title:
+ type: string
+ desc:
+ type: string
+ timeStart:
+ type: string
+ timeEnd:
+ type: string
+ dateStart:
+ type: string
+ repeatEventTyper:
+ type: string
+ repeatValue:
+ type: string
+ linkMeet:
+ type: string
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ user:
+ type: string
+ required:
+ - idDivision
+ - title
+ - desc
+ - timeStart
+ - timeEnd
+ - dateStart
+ - user
+
+ # Task
+ Task:
+ type: object
+ properties:
+ id:
+ type: string
+ title:
+ type: string
+ user:
+ type: string
+ status:
+ type: integer
+ idDivision:
+ type: string
+ required:
+ - id
+ - title
+
+ TaskCreateBody:
+ type: object
+ properties:
+ title:
+ type: string
+ description:
+ type: string
+ required:
+ - title
+
+ TaskTugasCreateBody:
+ type: object
+ properties:
+ title:
+ type: string
+ dateStart:
+ type: string
+ dateEnd:
+ type: string
+ user:
+ type: string
+ idDivision:
+ type: string
+ dataDetail:
+ type: array
+ items:
+ type: object
+ required:
+ - title
+ - dateStart
+ - dateEnd
+ - user
+ - idDivision
+
+ TaskMemberBody:
+ type: object
+ properties:
+ user:
+ type: string
+ member:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ idDivision:
+ type: string
+ required:
+ - user
+ - member
+ - idDivision
+
+ # Document
+ DocumentMoveBody:
+ type: object
+ properties:
+ path:
+ type: string
+ dataItem:
+ type: array
+ items:
+ type: object
+ user:
+ type: string
+ required:
+ - path
+ - dataItem
+ - user
+
+ DocumentCopyBody:
+ type: object
+ properties:
+ path:
+ type: string
+ dataItem:
+ type: array
+ items:
+ type: object
+ user:
+ type: string
+ idDivision:
+ type: string
+ required:
+ - path
+ - dataItem
+ - user
+ - idDivision
+
+ DocumentShareBody:
+ type: object
+ properties:
+ dataDivision:
+ type: array
+ items:
+ type: object
+ dataItem:
+ type: array
+ items:
+ type: object
+ user:
+ type: string
+ required:
+ - dataDivision
+ - dataItem
+ - user
+
+ DocumentRenameBody:
+ type: object
+ properties:
+ name:
+ type: string
+ user:
+ type: string
+ id:
+ type: string
+ path:
+ type: string
+ idDivision:
+ type: string
+ extension:
+ type: string
+ required:
+ - name
+ - user
+ - id
+ - path
+ - idDivision
+ - extension
+
+ DocumentFolderCreateBody:
+ type: object
+ properties:
+ name:
+ type: string
+ path:
+ type: string
+ idDivision:
+ type: string
+ user:
+ type: string
+ required:
+ - name
+ - path
+ - idDivision
+ - user
+
+ DocumentDeleteBody:
+ type: object
+ properties:
+ user:
+ type: string
+ data:
+ type: array
+ items:
+ type: object
+ required:
+ - user
+ - data
+
+ # Notification
+ NotificationReadBody:
+ type: object
+ properties:
+ user:
+ type: string
+ id:
+ type: string
+ required:
+ - user
+ - id
+
+ # Token
+ TokenBody:
+ type: object
+ properties:
+ user:
+ type: string
+ token:
+ type: string
+ required:
+ - user
+ - token
+
+ # Generic Response
+ ApiResponse:
+ type: object
+ properties:
+ data:
+ type: object
+ success:
+ type: boolean
+ required:
+ - data
+
+paths:
+ # Auth
+ /auth/login:
+ post:
+ tags:
+ - Auth
+ summary: Check phone for login
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PhoneLoginBody'
+ responses:
+ '200':
+ description: Login data
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ default:
+ description: Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+
+ # Banner
+ /mobile/banner:
+ get:
+ tags:
+ - Banner
+ summary: Get banners
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of banners
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Banner'
+ post:
+ tags:
+ - Banner
+ summary: Create banner
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ title:
+ type: string
+ image:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: Created banner
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Banner'
+
+ /mobile/banner/{id}:
+ get:
+ tags:
+ - Banner
+ summary: Get one banner
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Banner details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Banner'
+ put:
+ tags:
+ - Banner
+ summary: Edit banner
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ title:
+ type: string
+ image:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: Updated banner
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Banner'
+ delete:
+ tags:
+ - Banner
+ summary: Delete banner
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ required:
+ - user
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # Home Data
+ /mobile/home:
+ get:
+ tags:
+ - Home
+ summary: Get home data by category
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ enum: [kegiatan, division, progress, dokumen, event, discussion, header, check-late-project]
+ responses:
+ '200':
+ description: Home data
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/home/search:
+ get:
+ tags:
+ - Home
+ summary: Search home
+ parameters:
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Search results
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+
+ /mobile/home/notification:
+ get:
+ tags:
+ - Notification
+ summary: Get notifications
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of notifications
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ put:
+ tags:
+ - Notification
+ summary: Read one notification
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotificationReadBody'
+ responses:
+ '200':
+ description: Updated notification
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # Group
+ /mobile/group:
+ get:
+ tags:
+ - Group
+ summary: Get groups
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: active
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of groups
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Group'
+ post:
+ tags:
+ - Group
+ summary: Create group
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GroupCreateBody'
+ responses:
+ '200':
+ description: Created group
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Group'
+
+ /mobile/group/{id}:
+ put:
+ tags:
+ - Group
+ summary: Edit group
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GroupCreateBody'
+ responses:
+ '200':
+ description: Updated group
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Group'
+ delete:
+ tags:
+ - Group
+ summary: Delete group
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ isActive:
+ type: boolean
+ required:
+ - user
+ - isActive
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/group/get-division:
+ get:
+ tags:
+ - Group
+ summary: Get division groups
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Division groups
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Group'
+
+ # Position
+ /mobile/position:
+ get:
+ tags:
+ - Position
+ summary: Get positions
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: active
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: group
+ in: query
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of positions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Position'
+ post:
+ tags:
+ - Position
+ summary: Create position
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PositionCreateBody'
+ responses:
+ '200':
+ description: Created position
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Position'
+
+ /mobile/position/{id}:
+ put:
+ tags:
+ - Position
+ summary: Edit position
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PositionCreateBody'
+ responses:
+ '200':
+ description: Updated position
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Position'
+ delete:
+ tags:
+ - Position
+ summary: Delete position
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ isActive:
+ type: boolean
+ required:
+ - user
+ - isActive
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # User
+ /mobile/user:
+ get:
+ tags:
+ - User
+ summary: Get users
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: active
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: group
+ in: query
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of users
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ post:
+ tags:
+ - User
+ summary: Create user
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/UserCreateBody'
+ responses:
+ '200':
+ description: Created user
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+
+ /mobile/user/{id}:
+ get:
+ tags:
+ - User
+ summary: Get profile
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: User profile
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ put:
+ tags:
+ - User
+ summary: Edit user
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ photo:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: Updated user
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ delete:
+ tags:
+ - User
+ summary: Delete user
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ isActive:
+ type: boolean
+ required:
+ - user
+ - isActive
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/user/profile:
+ put:
+ tags:
+ - User
+ summary: Edit profile
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ photo:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: Updated profile
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+
+ # Discussion General
+ /mobile/discussion-general:
+ get:
+ tags:
+ - DiscussionGeneral
+ summary: Get discussion general
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: active
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: group
+ in: query
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of discussions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/DiscussionGeneral'
+ post:
+ tags:
+ - DiscussionGeneral
+ summary: Create discussion general
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionGeneralCreateBody'
+ responses:
+ '200':
+ description: Created discussion
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionGeneral'
+
+ /mobile/discussion-general/{id}:
+ get:
+ tags:
+ - DiscussionGeneral
+ summary: Get one discussion general
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Discussion details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionGeneral'
+ post:
+ tags:
+ - DiscussionGeneral
+ summary: Update status discussion general
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ status:
+ type: integer
+ user:
+ type: string
+ required:
+ - status
+ - user
+ responses:
+ '200':
+ description: Updated status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionGeneral'
+ put:
+ tags:
+ - DiscussionGeneral
+ summary: Edit discussion general
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ title:
+ type: string
+ desc:
+ type: string
+ required:
+ - user
+ - title
+ - desc
+ responses:
+ '200':
+ description: Updated discussion
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionGeneral'
+ delete:
+ tags:
+ - DiscussionGeneral
+ summary: Delete discussion general
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ active:
+ type: boolean
+ required:
+ - user
+ - active
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/discussion-general/{id}/comment:
+ post:
+ tags:
+ - DiscussionGeneral
+ summary: Send comment to discussion general
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionGeneralCommentBody'
+ responses:
+ '200':
+ description: Comment added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/discussion-general/{id}/member:
+ post:
+ tags:
+ - DiscussionGeneral
+ summary: Add members to discussion general
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DivisionMemberBody'
+ responses:
+ '200':
+ description: Members added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - DiscussionGeneral
+ summary: Delete member from discussion general
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ idUser:
+ type: string
+ required:
+ - user
+ - idUser
+ responses:
+ '200':
+ description: Member deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # Announcement
+ /mobile/announcement:
+ get:
+ tags:
+ - Announcement
+ summary: Get announcements
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of announcements
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Announcement'
+ post:
+ tags:
+ - Announcement
+ summary: Create announcement
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AnnouncementCreateBody'
+ responses:
+ '200':
+ description: Created announcement
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Announcement'
+
+ /mobile/announcement/{id}:
+ get:
+ tags:
+ - Announcement
+ summary: Get one announcement
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Announcement details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Announcement'
+ put:
+ tags:
+ - Announcement
+ summary: Edit announcement
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AnnouncementCreateBody'
+ responses:
+ '200':
+ description: Updated announcement
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Announcement'
+ delete:
+ tags:
+ - Announcement
+ summary: Delete announcement
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ required:
+ - user
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # Project
+ /mobile/project:
+ get:
+ tags:
+ - Project
+ summary: Get projects
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: status
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: group
+ in: query
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of projects
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Project'
+ post:
+ tags:
+ - Project
+ summary: Create project
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/ProjectCreateBody'
+ responses:
+ '200':
+ description: Created project
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+
+ /mobile/project/{id}:
+ get:
+ tags:
+ - Project
+ summary: Get one project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ enum: [data, progress, task, file, member, link]
+ responses:
+ '200':
+ description: Project details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ put:
+ tags:
+ - Project
+ summary: Edit project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ user:
+ type: string
+ required:
+ - name
+ - user
+ responses:
+ '200':
+ description: Updated project
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ post:
+ tags:
+ - Project
+ summary: Create project task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectTaskCreateBody'
+ responses:
+ '200':
+ description: Created task
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Project
+ summary: Cancel project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ reason:
+ type: string
+ required:
+ - user
+ - reason
+ responses:
+ '200':
+ description: Canceled
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/project/{id}/lainnya:
+ put:
+ tags:
+ - Project
+ summary: Report project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ report:
+ type: string
+ user:
+ type: string
+ required:
+ - report
+ - user
+ responses:
+ '200':
+ description: Report added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Project
+ summary: Delete project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ required:
+ - user
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/project/detail/{id}:
+ get:
+ tags:
+ - Project
+ summary: Get project task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Task details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ put:
+ tags:
+ - Project
+ summary: Update status project task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectUpdateStatusBody'
+ responses:
+ '200':
+ description: Status updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ post:
+ tags:
+ - Project
+ summary: Edit project task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectTaskCreateBody'
+ responses:
+ '200':
+ description: Task updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Project
+ summary: Delete project task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ idProject:
+ type: string
+ required:
+ - user
+ - idProject
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/project/{id}/member:
+ post:
+ tags:
+ - Project
+ summary: Add members to project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DivisionMemberBody'
+ responses:
+ '200':
+ description: Members added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Project
+ summary: Delete member from project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ idUser:
+ type: string
+ required:
+ - user
+ - idUser
+ responses:
+ '200':
+ description: Member deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/project/{id}/link:
+ post:
+ tags:
+ - Project
+ summary: Add link to project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ link:
+ type: string
+ required:
+ - user
+ - link
+ responses:
+ '200':
+ description: Link added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Project
+ summary: Delete link from project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ idLink:
+ type: string
+ user:
+ type: string
+ required:
+ - idLink
+ - user
+ responses:
+ '200':
+ description: Link deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/project/file/{id}:
+ post:
+ tags:
+ - Project
+ summary: Add file to project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ file:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: File added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ put:
+ tags:
+ - Project
+ summary: Check/update file in project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ file:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: File updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Project
+ summary: Delete file from project
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ required:
+ - user
+ responses:
+ '200':
+ description: File deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # Division
+ /mobile/division:
+ get:
+ tags:
+ - Division
+ summary: Get divisions
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: active
+ in: query
+ schema:
+ type: string
+ - name: group
+ in: query
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of divisions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Division'
+ post:
+ tags:
+ - Division
+ summary: Create division
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DivisionCreateBody'
+ responses:
+ '200':
+ description: Created division
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Division'
+
+ /mobile/division/{id}:
+ get:
+ tags:
+ - Division
+ summary: Get one division detail
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Division details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Division'
+ put:
+ tags:
+ - Division
+ summary: Edit division
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ name:
+ type: string
+ desc:
+ type: string
+ required:
+ - user
+ - name
+ - desc
+ responses:
+ '200':
+ description: Updated division
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Division'
+
+ /mobile/division/{id}/detail:
+ get:
+ tags:
+ - Division
+ summary: Get division one feature
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ enum: [jumlah, today-task, new-file, new-discussion, check-member, check-admin]
+ responses:
+ '200':
+ description: Feature data
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ put:
+ tags:
+ - Division
+ summary: Update status admin division
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ id:
+ type: string
+ isAdmin:
+ type: boolean
+ required:
+ - user
+ - id
+ - isAdmin
+ responses:
+ '200':
+ description: Status updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ post:
+ tags:
+ - Division
+ summary: Add members to division
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DivisionMemberBody'
+ responses:
+ '200':
+ description: Members added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Division
+ summary: Delete member from division
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ id:
+ type: string
+ required:
+ - user
+ - id
+ responses:
+ '200':
+ description: Member deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/division/{id}/status:
+ post:
+ tags:
+ - Division
+ summary: Update status division
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ isActive:
+ type: boolean
+ required:
+ - user
+ - isActive
+ responses:
+ '200':
+ description: Status updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/division/{id}/member:
+ get:
+ tags:
+ - Division
+ summary: Get division members
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of members
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+
+ /mobile/division/report:
+ get:
+ tags:
+ - Division
+ summary: Get division report
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ enum: [table-progress, lainnya]
+ - name: date
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: date-end
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: group
+ in: query
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Report data
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/division/more:
+ get:
+ tags:
+ - Division
+ summary: Get list division by id division
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of divisions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Division'
+
+ # Discussion
+ /mobile/discussion:
+ get:
+ tags:
+ - Discussion
+ summary: Get discussions
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: active
+ in: query
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of discussions
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Discussion'
+ post:
+ tags:
+ - Discussion
+ summary: Create discussion
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionCreateBody'
+ responses:
+ '200':
+ description: Created discussion
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Discussion'
+
+ /mobile/discussion/{id}:
+ get:
+ tags:
+ - Discussion
+ summary: Get one discussion
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ enum: [data, comment]
+ responses:
+ '200':
+ description: Discussion details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Discussion'
+ post:
+ tags:
+ - Discussion
+ summary: Edit discussion
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionEditBody'
+ responses:
+ '200':
+ description: Updated discussion
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Discussion'
+ put:
+ tags:
+ - Discussion
+ summary: Archive discussion
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ active:
+ type: boolean
+ required:
+ - user
+ - active
+ responses:
+ '200':
+ description: Archived
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Discussion
+ summary: Open/close discussion
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ status:
+ type: integer
+ required:
+ - user
+ - status
+ responses:
+ '200':
+ description: Status updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/discussion/{id}/comment:
+ post:
+ tags:
+ - Discussion
+ summary: Send comment to discussion
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscussionCommentBody'
+ responses:
+ '200':
+ description: Comment added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # Calendar
+ /mobile/calendar:
+ get:
+ tags:
+ - Calendar
+ summary: Get calendar by date and division
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: date
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Calendar events
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Calendar'
+ post:
+ tags:
+ - Calendar
+ summary: Create calendar event
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CalendarCreateBody'
+ responses:
+ '200':
+ description: Created event
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Calendar'
+
+ /mobile/calendar/indicator:
+ get:
+ tags:
+ - Calendar
+ summary: Get calendar indicator
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: date
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Indicators
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/calendar/{id}:
+ get:
+ tags:
+ - Calendar
+ summary: Get one calendar event
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ enum: [data, member]
+ responses:
+ '200':
+ description: Event details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Calendar'
+ put:
+ tags:
+ - Calendar
+ summary: Update calendar event
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ title:
+ type: string
+ desc:
+ type: string
+ timeStart:
+ type: string
+ timeEnd:
+ type: string
+ dateStart:
+ type: string
+ repeatEventTyper:
+ type: string
+ repeatValue:
+ type: number
+ linkMeet:
+ type: string
+ user:
+ type: string
+ required:
+ - title
+ - desc
+ - timeStart
+ - timeEnd
+ - dateStart
+ - repeatEventTyper
+ - repeatValue
+ - linkMeet
+ - user
+ responses:
+ '200':
+ description: Updated event
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Calendar'
+ delete:
+ tags:
+ - Calendar
+ summary: Delete calendar event
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ required:
+ - user
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/calendar/{id}/member:
+ post:
+ tags:
+ - Calendar
+ summary: Add members to calendar
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DivisionMemberBody'
+ responses:
+ '200':
+ description: Members added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Calendar
+ summary: Delete member from calendar
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ idUser:
+ type: string
+ required:
+ - user
+ - idUser
+ responses:
+ '200':
+ description: Member deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/calendar/history:
+ get:
+ tags:
+ - Calendar
+ summary: Get calendar history
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: History
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Calendar'
+
+ # Task
+ /mobile/task:
+ get:
+ tags:
+ - Task
+ summary: Get tasks
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: status
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: search
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: page
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of tasks
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Task'
+ post:
+ tags:
+ - Task
+ summary: Create task
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/TaskCreateBody'
+ responses:
+ '200':
+ description: Created task
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Task'
+
+ /mobile/task/{id}:
+ get:
+ tags:
+ - Task
+ summary: Get one task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ required: true
+ schema:
+ type: string
+ enum: [data, progress, task, file, member, link]
+ responses:
+ '200':
+ description: Task details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Task'
+ put:
+ tags:
+ - Task
+ summary: Edit task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ title:
+ type: string
+ user:
+ type: string
+ required:
+ - title
+ - user
+ responses:
+ '200':
+ description: Updated task
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Task'
+ post:
+ tags:
+ - Task
+ summary: Create task tugas
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TaskTugasCreateBody'
+ responses:
+ '200':
+ description: Created tugas
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Task
+ summary: Cancel task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ reason:
+ type: string
+ required:
+ - user
+ - reason
+ responses:
+ '200':
+ description: Canceled
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/task/{id}/lainnya:
+ put:
+ tags:
+ - Task
+ summary: Report task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ report:
+ type: string
+ user:
+ type: string
+ required:
+ - report
+ - user
+ responses:
+ '200':
+ description: Report added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Task
+ summary: Delete task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ required:
+ - user
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/task/detail/{id}:
+ get:
+ tags:
+ - Task
+ summary: Get task tugas
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: cat
+ in: query
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Tugas details
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ put:
+ tags:
+ - Task
+ summary: Update status task division
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectUpdateStatusBody'
+ responses:
+ '200':
+ description: Status updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ post:
+ tags:
+ - Task
+ summary: Edit task tugas
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TaskTugasCreateBody'
+ responses:
+ '200':
+ description: Tugas updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Task
+ summary: Delete task tugas
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ idProject:
+ type: string
+ required:
+ - user
+ - idProject
+ responses:
+ '200':
+ description: Deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/task/{id}/member:
+ post:
+ tags:
+ - Task
+ summary: Add members to task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TaskMemberBody'
+ responses:
+ '200':
+ description: Members added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Task
+ summary: Delete member from task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ idUser:
+ type: string
+ required:
+ - user
+ - idUser
+ responses:
+ '200':
+ description: Member deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/task/{id}/link:
+ post:
+ tags:
+ - Task
+ summary: Add link to task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ link:
+ type: string
+ idDivision:
+ type: string
+ required:
+ - user
+ - link
+ - idDivision
+ responses:
+ '200':
+ description: Link added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Task
+ summary: Delete link from task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ idLink:
+ type: string
+ required:
+ - user
+ - idLink
+ responses:
+ '200':
+ description: Link deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ /mobile/task/file/{id}:
+ post:
+ tags:
+ - Task
+ summary: Add file to task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ file:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: File added
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ put:
+ tags:
+ - Task
+ summary: Check/update file in task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ file:
+ type: string
+ format: binary
+ responses:
+ '200':
+ description: File updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+ delete:
+ tags:
+ - Task
+ summary: Delete file from task
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ user:
+ type: string
+ required:
+ - user
+ responses:
+ '200':
+ description: File deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiResponse'
+
+ # Document
+ /mobile/document:
+ get:
+ tags:
+ - Document
+ summary: Get documents
+ parameters:
+ - name: user
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: path
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: division
+ in: query
+ required:
\ No newline at end of file
diff --git a/downloads/dataMessage.json b/downloads/dataMessage.json
deleted file mode 100644
index 5ca3190..0000000
--- a/downloads/dataMessage.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "from": "6289505046093@c.us",
- "fromMe": false,
- "body": "halo gaes",
- "hasMedia": false,
- "type": "chat",
- "to": "6289697338821@c.us",
- "deviceType": "android",
- "media": {
- "data": null,
- "mimetype": null,
- "filename": null,
- "filesize": null
- },
- "notifyName": "jenna ai"
-}
\ No newline at end of file
diff --git a/downloads/fullChat.json b/downloads/fullChat.json
deleted file mode 100644
index 4f4be69..0000000
--- a/downloads/fullChat.json
+++ /dev/null
@@ -1,187 +0,0 @@
-{
- "_data": {
- "id": {
- "fromMe": false,
- "remote": "6289505046093@c.us",
- "id": "AC240D892DE952C48F68249C8D3CAF65",
- "_serialized": "false_6289505046093@c.us_AC240D892DE952C48F68249C8D3CAF65"
- },
- "viewed": false,
- "body": "halo gaes",
- "type": "chat",
- "t": 1760499333,
- "clientReceivedTsMillis": 1760499331816,
- "notifyName": "jenna ai",
- "from": "6289505046093@c.us",
- "to": "6289697338821@c.us",
- "ack": 1,
- "invis": false,
- "isNewMsg": true,
- "star": false,
- "kicNotified": false,
- "recvFresh": true,
- "isFromTemplate": false,
- "thumbnail": "",
- "richPreviewType": 0,
- "faviconMMSMetadata": null,
- "pollInvalidated": false,
- "isSentCagPollCreation": false,
- "latestEditMsgKey": null,
- "latestEditSenderTimestampMs": null,
- "mentionedJidList": [],
- "groupMentions": [],
- "isEventCanceled": false,
- "eventInvalidated": false,
- "isVcardOverMmsDocument": false,
- "questionReplyQuotedMessage": null,
- "questionResponsesCount": 0,
- "readQuestionResponsesCount": 0,
- "hasReaction": false,
- "ephemeralDuration": 86400,
- "ephemeralSettingTimestamp": 1760421708,
- "disappearingModeInitiator": "chat",
- "disappearingModeTrigger": "chat_settings",
- "disappearingModeInitiatedByMe": false,
- "viewMode": "VISIBLE",
- "messageSecret": {
- "0": 120,
- "1": 16,
- "2": 223,
- "3": 31,
- "4": 255,
- "5": 95,
- "6": 54,
- "7": 23,
- "8": 5,
- "9": 170,
- "10": 126,
- "11": 183,
- "12": 142,
- "13": 88,
- "14": 30,
- "15": 251,
- "16": 81,
- "17": 183,
- "18": 16,
- "19": 69,
- "20": 158,
- "21": 252,
- "22": 148,
- "23": 155,
- "24": 40,
- "25": 5,
- "26": 20,
- "27": 210,
- "28": 140,
- "29": 42,
- "30": 6,
- "31": 123
- },
- "inviteGrpType": "DEFAULT",
- "productHeaderImageRejected": false,
- "lastPlaybackProgress": 0,
- "isDynamicReplyButtonsMsg": false,
- "isCarouselCard": false,
- "parentMsgId": null,
- "callSilenceReason": null,
- "isVideoCall": false,
- "callDuration": null,
- "callCreator": null,
- "callParticipants": null,
- "isCallLink": null,
- "callLinkToken": null,
- "isMdHistoryMsg": false,
- "stickerSentTs": 0,
- "isAvatar": false,
- "lastUpdateFromServerTs": 0,
- "invokedBotWid": null,
- "bizBotType": null,
- "botResponseTargetId": null,
- "botPluginType": null,
- "botPluginReferenceIndex": null,
- "botPluginSearchProvider": null,
- "botPluginSearchUrl": null,
- "botPluginSearchQuery": null,
- "botPluginMaybeParent": false,
- "botReelPluginThumbnailCdnUrl": null,
- "botMessageDisclaimerText": null,
- "botMsgBodyType": null,
- "reportingTokenInfo": {
- "reportingToken": {
- "0": 75,
- "1": 111,
- "2": 0,
- "3": 170,
- "4": 128,
- "5": 198,
- "6": 97,
- "7": 213,
- "8": 204,
- "9": 150,
- "10": 169,
- "11": 92,
- "12": 233,
- "13": 114,
- "14": 228,
- "15": 203
- },
- "version": 2,
- "reportingTag": {
- "0": 1,
- "1": 11,
- "2": 67,
- "3": 48,
- "4": 159,
- "5": 94,
- "6": 8,
- "7": 153,
- "8": 152,
- "9": 19,
- "10": 22,
- "11": 148,
- "12": 143,
- "13": 89,
- "14": 9,
- "15": 64,
- "16": 248,
- "17": 149,
- "18": 74,
- "19": 64
- }
- },
- "requiresDirectConnection": null,
- "bizContentPlaceholderType": null,
- "hostedBizEncStateMismatch": false,
- "senderOrRecipientAccountTypeHosted": false,
- "placeholderCreatedWhenAccountIsHosted": false,
- "galaxyFlowDisabled": false,
- "groupHistoryBundleMessageKey": null,
- "groupHistoryBundleMetadata": null,
- "links": []
- },
- "id": {
- "fromMe": false,
- "remote": "6289505046093@c.us",
- "id": "AC240D892DE952C48F68249C8D3CAF65",
- "_serialized": "false_6289505046093@c.us_AC240D892DE952C48F68249C8D3CAF65"
- },
- "ack": 1,
- "hasMedia": false,
- "body": "halo gaes",
- "type": "chat",
- "timestamp": 1760499333,
- "from": "6289505046093@c.us",
- "to": "6289697338821@c.us",
- "deviceType": "android",
- "forwardingScore": 0,
- "isStatus": false,
- "isStarred": false,
- "fromMe": false,
- "hasQuotedMsg": false,
- "hasReaction": false,
- "vCards": [],
- "mentionedIds": [],
- "groupMentions": [],
- "isGif": false,
- "links": []
-}
\ No newline at end of file
diff --git a/downloads/media.json b/downloads/media.json
deleted file mode 100644
index 985ae5a..0000000
--- a/downloads/media.json
+++ /dev/null
@@ -1,205 +0,0 @@
-{
- "_data": {
- "id": {
- "fromMe": false,
- "remote": "6289505046093@c.us",
- "id": "AC1FCF4C63F9B86F93313AAEC7EC5AE5",
- "_serialized": "false_6289505046093@c.us_AC1FCF4C63F9B86F93313AAEC7EC5AE5"
- },
- "viewed": false,
- "body": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEABsbGxscGx4hIR4qLSgtKj04MzM4PV1CR0JHQl2NWGdYWGdYjX2Xe3N7l33gsJycsOD/2c7Z//////////////8BGxsbGxwbHiEhHiotKC0qPTgzMzg9XUJHQkdCXY1YZ1hYZ1iNfZd7c3uXfeCwnJyw4P/Zztn////////////////CABEIADwAIQMBIgACEQEDEQH/xAAuAAADAQEBAQAAAAAAAAAAAAAAAwQCBQEGAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAOtUim5zh/qzFIcWnm3xczjuOoSC/LYkLHsl0WEYOJdj8JoXJUH/xAAlEAACAQIFBAMBAAAAAAAAAAABAgADEQQSEyFREBQxQSIyUmH/2gAIAQEAAT8Aoow+LGaZ5mn/AGGgD5M7ZeeibqJbqMaL2KxMaoNrbRcRSbw0V1bwb9HRTUFvZmgqreZ6ak7i0SsFU5CJ3MoYrTDFtz6jYmqxPzIBmc8xXb0016v7nqXgm83jUXdjZReDCVPewgw1Q+CI1Kqm5E1W4mZuTNR7fYzO36MpVX8Xm3An/8QAFxEBAQEBAAAAAAAAAAAAAAAAEQABMP/aAAgBAgEBPwB2Z3iX/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQARMP/aAAgBAwEBPwACyw463//Z",
- "type": "image",
- "t": 1760499162,
- "clientReceivedTsMillis": 1760499161349,
- "notifyName": "jenna ai",
- "from": "6289505046093@c.us",
- "to": "6289697338821@c.us",
- "ack": 1,
- "invis": false,
- "isNewMsg": true,
- "star": false,
- "kicNotified": false,
- "recvFresh": true,
- "interactiveAnnotations": [],
- "deprecatedMms3Url": "https://mmg.whatsapp.net/v/t62.7118-24/565618455_32971919975740209_8438009621194429801_n.enc?ccb=11-4&oh=01_Q5Aa2wEh_OAabe-vO_8PiWdXDveV3I7vgykLw6MjCihpQdmq7w&oe=69169DCC&_nc_sid=5e03e0&mms3=true",
- "directPath": "/v/t62.7118-24/565618455_32971919975740209_8438009621194429801_n.enc?ccb=11-4&oh=01_Q5Aa2wEh_OAabe-vO_8PiWdXDveV3I7vgykLw6MjCihpQdmq7w&oe=69169DCC&_nc_sid=5e03e0",
- "mimetype": "image/jpeg",
- "filehash": "IveoyrubZqm4f8VrvH5lU9zN/M6kXddXM6GchNIoBf8=",
- "encFilehash": "LP/NA3twuiOjLyl7bnq6Tavsu7MT0hKa2v0/ts0wkzI=",
- "size": 47276,
- "mediaKey": "7eEyqrxGDsJXoGIBxbmeo2PdbO0T+I8KcSqZWJmfvLo=",
- "mediaKeyTimestamp": 1760498519,
- "isViewOnce": false,
- "width": 720,
- "height": 1280,
- "staticUrl": "",
- "scanLengths": [
- 7339,
- 17711,
- 7801,
- 14425
- ],
- "scansSidecar": {},
- "isFromTemplate": false,
- "pollInvalidated": false,
- "isSentCagPollCreation": false,
- "latestEditMsgKey": null,
- "latestEditSenderTimestampMs": null,
- "mentionedJidList": [],
- "groupMentions": [],
- "isEventCanceled": false,
- "eventInvalidated": false,
- "statusMentioned": false,
- "isVcardOverMmsDocument": false,
- "questionReplyQuotedMessage": null,
- "questionResponsesCount": 0,
- "readQuestionResponsesCount": 0,
- "hasReaction": false,
- "ephemeralDuration": 86400,
- "ephemeralSettingTimestamp": 1760421708,
- "disappearingModeInitiator": "chat",
- "disappearingModeTrigger": "chat_settings",
- "disappearingModeInitiatedByMe": false,
- "viewMode": "VISIBLE",
- "messageSecret": {
- "0": 29,
- "1": 141,
- "2": 90,
- "3": 218,
- "4": 12,
- "5": 186,
- "6": 69,
- "7": 134,
- "8": 140,
- "9": 175,
- "10": 233,
- "11": 234,
- "12": 147,
- "13": 5,
- "14": 112,
- "15": 20,
- "16": 135,
- "17": 4,
- "18": 190,
- "19": 145,
- "20": 68,
- "21": 243,
- "22": 86,
- "23": 109,
- "24": 9,
- "25": 235,
- "26": 250,
- "27": 31,
- "28": 255,
- "29": 149,
- "30": 147,
- "31": 124
- },
- "productHeaderImageRejected": false,
- "lastPlaybackProgress": 0,
- "isDynamicReplyButtonsMsg": false,
- "isCarouselCard": false,
- "parentMsgId": null,
- "callSilenceReason": null,
- "isVideoCall": false,
- "callDuration": null,
- "callCreator": null,
- "callParticipants": null,
- "isCallLink": null,
- "callLinkToken": null,
- "isMdHistoryMsg": false,
- "stickerSentTs": 0,
- "isAvatar": false,
- "lastUpdateFromServerTs": 0,
- "invokedBotWid": null,
- "bizBotType": null,
- "botResponseTargetId": null,
- "botPluginType": null,
- "botPluginReferenceIndex": null,
- "botPluginSearchProvider": null,
- "botPluginSearchUrl": null,
- "botPluginSearchQuery": null,
- "botPluginMaybeParent": false,
- "botReelPluginThumbnailCdnUrl": null,
- "botMessageDisclaimerText": null,
- "botMsgBodyType": null,
- "reportingTokenInfo": {
- "reportingToken": {
- "0": 22,
- "1": 36,
- "2": 226,
- "3": 57,
- "4": 30,
- "5": 125,
- "6": 123,
- "7": 89,
- "8": 148,
- "9": 96,
- "10": 59,
- "11": 132,
- "12": 196,
- "13": 230,
- "14": 192,
- "15": 44
- },
- "version": 2,
- "reportingTag": {
- "0": 1,
- "1": 11,
- "2": 216,
- "3": 114,
- "4": 105,
- "5": 176,
- "6": 57,
- "7": 186,
- "8": 62,
- "9": 102,
- "10": 166,
- "11": 62,
- "12": 206,
- "13": 161,
- "14": 215,
- "15": 245,
- "16": 83,
- "17": 227,
- "18": 232,
- "19": 76
- }
- },
- "requiresDirectConnection": null,
- "bizContentPlaceholderType": null,
- "hostedBizEncStateMismatch": false,
- "senderOrRecipientAccountTypeHosted": false,
- "placeholderCreatedWhenAccountIsHosted": false,
- "galaxyFlowDisabled": false,
- "groupHistoryBundleMessageKey": null,
- "groupHistoryBundleMetadata": null,
- "links": []
- },
- "mediaKey": "7eEyqrxGDsJXoGIBxbmeo2PdbO0T+I8KcSqZWJmfvLo=",
- "id": {
- "fromMe": false,
- "remote": "6289505046093@c.us",
- "id": "AC1FCF4C63F9B86F93313AAEC7EC5AE5",
- "_serialized": "false_6289505046093@c.us_AC1FCF4C63F9B86F93313AAEC7EC5AE5"
- },
- "ack": 1,
- "hasMedia": true,
- "body": "",
- "type": "image",
- "timestamp": 1760499162,
- "from": "6289505046093@c.us",
- "to": "6289697338821@c.us",
- "deviceType": "android",
- "forwardingScore": 0,
- "isStatus": false,
- "isStarred": false,
- "fromMe": false,
- "hasQuotedMsg": false,
- "hasReaction": false,
- "vCards": [],
- "mentionedIds": [],
- "groupMentions": [],
- "isGif": false,
- "links": []
-}
\ No newline at end of file
diff --git a/package.json b/package.json
index b43155f..d0ee594 100644
--- a/package.json
+++ b/package.json
@@ -26,9 +26,12 @@
"@types/lodash": "^4.17.20",
"@types/qrcode-terminal": "^0.12.2",
"add": "^2.0.6",
+ "colors": "^1.4.0",
"elysia": "^1.4.11",
+ "form-data": "^4.0.4",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
+ "node-fetch": "^3.3.2",
"qrcode-terminal": "^0.12.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
diff --git a/proposal.md b/proposal.md
new file mode 100644
index 0000000..10eb56f
--- /dev/null
+++ b/proposal.md
@@ -0,0 +1,76 @@
+
+PROPOSAL PEMEKARAN TIM DIVISI PENGEMBANGAN
+Proyek: Jenna AI – Lalu Lintas Badung & Jenna Darmasaba
+Lokasi: Kuta / Badung, Bali
+========================================================
+
+### 1. LATAR BELAKANG
+Dalam rangka mendukung pengembangan dan ekspansi proyek **Jenna AI** pada dua wilayah operasional, yaitu **Lalu Lintas Badung** dan **Jenna Darmasaba**, diperlukan pemekaran pada tim **Divisi Pengembangan (Developer)**.
+Pemekaran ini bertujuan untuk memperkuat kapasitas teknis, mempercepat inovasi fitur, memastikan kestabilan sistem, serta meningkatkan kualitas integrasi antara platform WhatsApp, AI Engine, dan infrastruktur pendukung yang digunakan Jenna AI.
+
+---
+
+### 2. TUJUAN PEMEKARAN
+- Memperluas kapabilitas tim dalam pengembangan sistem berbasis AI, NLP, dan integrasi real-time.
+- Meningkatkan kecepatan pengembangan dan keandalan (reliability) sistem Jenna di dua wilayah operasional.
+- Mempersiapkan tim teknis yang mampu menjaga skalabilitas, keamanan, dan performa sistem.
+- Menjamin kesinambungan inovasi pada produk Jenna, termasuk optimalisasi model AI dan pengelolaan LLM (Large Language Model) Ops.
+
+---
+
+### 3. STRUKTUR DAN KOMPONEN TIM
+Berikut adalah susunan personel untuk **Divisi Pengembangan (Developer)** hasil pemekaran, disesuaikan dengan kebutuhan proyek di Bali:
+
+| Posisi | Jumlah | Gaji / Bulan (IDR) | Subtotal |
+|--------|---------|--------------------|-----------|
+| Technical Lead / Architect | 1 | 60.000.000 | 60.000.000 |
+| Backend Engineer | 3 | 27.000.000 | 81.000.000 |
+| Frontend Engineer | 2 | 25.000.000 | 50.000.000 |
+| Mobile Engineer | 1 | 27.000.000 | 27.000.000 |
+| DevOps / SRE | 1 | 35.000.000 | 35.000.000 |
+| AI / ML Engineer | 2 | 40.000.000 | 80.000.000 |
+| NLP / Conversational Engineer | 1 | 40.000.000 | 40.000.000 |
+| Data Engineer | 1 | 35.000.000 | 35.000.000 |
+| UI/UX Designer | 1 | 20.000.000 | 20.000.000 |
+| Intern / Junior Developer | 2 | 6.000.000 | 12.000.000 |
+| **TOTAL** | **12 Orang** | | **Rp 440.000.000 / bulan** |
+
+---
+
+### 4. ESTIMASI BIAYA PENDUKUNG
+Tambahan biaya untuk benefit, tools, dan kontinjensi operasional:
+
+| Komponen | Persentase | Estimasi / Bulan (IDR) |
+|-----------|-------------|-------------------------|
+| Benefit (BPJS, tunjangan, alat kerja, software, coworking, pelatihan) | +20% | 88.000.000 |
+| Kontinjensi (freelance tambahan, overtime, training AI, upgrade infrastruktur) | +15% | 66.000.000 |
+| **TOTAL ESTIMASI BULANAN (All-In)** | | **Rp 594.000.000** |
+
+---
+
+### 5. ESTIMASI BIAYA TAHUNAN
+| Komponen | Estimasi / Tahun (IDR) |
+|-----------|------------------------|
+| Base Gaji Tahunan | 5.280.000.000 |
+| Dengan Benefit & Tools (20%) | 6.336.000.000 |
+| Dengan Kontinjensi (Total) | **7.128.000.000** |
+
+---
+
+### 6. CATATAN DAN PERTIMBANGAN
+- Estimasi ini menggunakan skenario **maksimum realistis** untuk wilayah Bali (Kuta/Badung).
+- Posisi AI Engineer, DevOps, dan Architect mengikuti standar nasional karena keterbatasan talenta di area lokal.
+- Struktur ini mencakup seluruh kompetensi inti pengembangan: backend, frontend, mobile, AI/NLP, data pipeline, DevOps, serta UI/UX.
+- Pemekaran ini diharapkan mampu mempercepat siklus pengembangan, menjaga stabilitas sistem lintas wilayah, serta memperkuat posisi Jenna AI sebagai platform layanan berbasis kecerdasan buatan yang andal.
+
+---
+
+### 7. PENUTUP
+Dengan mempertimbangkan peningkatan skala operasi, kompleksitas teknis, serta roadmap pengembangan AI Jenna, pemekaran tim **Divisi Pengembangan** ini menjadi langkah strategis untuk memastikan keberlanjutan dan daya saing sistem di masa depan.
+
+Estimasi di atas dapat dijadikan acuan dalam **pengajuan anggaran (budgeting)** serta **perencanaan sumber daya manusia** pada tahun berjalan.
+
+Disusun oleh:
+**[Nama Penyusun]**
+Divisi Teknologi & Pengembangan Jenna AI
+Badung, Bali — 2025
diff --git a/src/server/lib/wa/wa_service.ts b/src/server/lib/wa/wa_service.ts
index 12ef459..a18afd8 100644
--- a/src/server/lib/wa/wa_service.ts
+++ b/src/server/lib/wa/wa_service.ts
@@ -5,11 +5,19 @@ import path from 'path';
import { v4 as uuid } from 'uuid';
import { prisma } from '../prisma';
import { getValueByPath } from '../get_value_by_path';
+import "colors"
-// === KONFIGURASI UTAMA ===
const MEDIA_DIR = path.join(process.cwd(), 'downloads');
await ensureDir(MEDIA_DIR);
+async function ensureDir(dir: string) {
+ try {
+ await fs.access(dir);
+ } catch {
+ await fs.mkdir(dir, { recursive: true });
+ }
+}
+
type DataMessage = {
from: string;
fromNumber: string;
@@ -19,12 +27,7 @@ type DataMessage = {
type: WAWebJS.MessageTypes;
to: string;
deviceType: string;
- media: {
- data: WAWebJS.MessageMedia["data"];
- mimetype: WAWebJS.MessageMedia["mimetype"];
- filename: WAWebJS.MessageMedia["filename"];
- filesize: WAWebJS.MessageMedia["filesize"];
- };
+ media: any[] | null;
notifyName: string;
}
@@ -60,13 +63,6 @@ function log(...args: any[]) {
console.log(`[${new Date().toISOString()}]`, ...args);
}
-async function ensureDir(dir: string) {
- try {
- await fs.access(dir);
- } catch {
- await fs.mkdir(dir, { recursive: true });
- }
-}
async function safeRm(path: string) {
try {
@@ -95,6 +91,8 @@ async function destroyClient() {
}
}
+let connectedAt: number | null = null;
+
// === PEMBUATAN CLIENT ===
async function startClient() {
if (state.isStarting || state.isReconnecting) {
@@ -131,6 +129,7 @@ async function startClient() {
});
client.on('ready', () => {
+ connectedAt = Date.now();
log('✅ WhatsApp client siap digunakan!');
state.ready = true;
state.isReconnecting = false;
@@ -177,17 +176,32 @@ async function startClient() {
}
}
+function detectFileCategory(mime: string) {
+ if (mime.startsWith("image/")) return "image";
+ if (mime.startsWith("audio/")) return "audio";
+ if (mime.startsWith("video/")) return "video";
+ if (mime === "application/pdf") return "pdf";
+ if (mime.includes("spreadsheet") || mime.includes("excel")) return "excel";
+ if (mime.includes("word")) return "document";
+ if (mime.includes("presentation") || mime.includes("powerpoint")) return "presentation";
+ return "file";
+}
+
// === HANDLER PESAN MASUK ===
async function handleIncomingMessage(msg: WAWebJS.Message) {
+ const chat = await msg.getChat();
+ await chat.sendStateTyping();
log(`💬 Pesan dari ${msg.from}: ${msg.body || '[MEDIA]'}`);
+
+ if (!connectedAt) return;
+ if (msg.timestamp * 1000 < connectedAt) return;
+
if (msg.from.endsWith('@g.us') || msg.isStatus || msg.from === 'status@broadcast') {
log(`🚫 Pesan dari grup/status diabaikan (${msg.from})`);
return;
}
try {
-
- const body = msg.body?.toLowerCase().trim() || '';
const notifyName = (msg as any)._data.notifyName;
const dataMessage: DataMessage = {
@@ -199,32 +213,32 @@ async function handleIncomingMessage(msg: WAWebJS.Message) {
type: msg.type,
to: msg.to,
deviceType: msg.deviceType,
- media: {
- data: null as unknown as WAWebJS.MessageMedia['data'],
- mimetype: null as unknown as WAWebJS.MessageMedia['mimetype'],
- filename: null as unknown as WAWebJS.MessageMedia['filename'],
- filesize: null as unknown as WAWebJS.MessageMedia['filesize'],
-
- },
+ media: null,
notifyName,
};
- // Media handler
+ // === HANDLE MEDIA ===
if (msg.hasMedia) {
const media = await msg.downloadMedia();
- dataMessage.media = {
- data: media.data,
- mimetype: media.mimetype,
- filename: media.filename,
- filesize: media.filesize
- };
+ // Pastikan formatnya data:;base64,
+ const mime = media.mimetype || 'application/octet-stream';
+ const prefixedBase64 = `data:${mime};base64,${media.data}`;
+
+ dataMessage.media = [{
+ type: "file:full",
+ data: prefixedBase64,
+ mime: mime,
+ name: media.filename || `${uuid()}.${mime.split('/')[1] || 'bin'}`
+ }];
+
+ // await fs.writeFile(path.join(MEDIA_DIR, dataMessage.media[0].name), Buffer.from(media.data, 'base64'));
+
}
- // to web hook
+ // === KIRIM KE WEBHOOK ===
try {
const webhooks = await prisma.webHook.findMany({ where: { enabled: true } });
-
if (!webhooks.length) {
log('🚫 Tidak ada webhook yang aktif');
return;
@@ -233,8 +247,22 @@ async function handleIncomingMessage(msg: WAWebJS.Message) {
await Promise.allSettled(
webhooks.map(async (hook) => {
try {
- console.log("send webhook " + hook.url);
- const body = payloadConverter({ payload: hook.payload ?? JSON.stringify(dataMessage), data: dataMessage });
+ log(`🌐 Mengirim webhook ke ${hook.url}`);
+
+ let body = payloadConverter({
+ payload: hook.payload ?? JSON.stringify(dataMessage),
+ data: dataMessage,
+ });
+
+ if (dataMessage.hasMedia) {
+ const bodyMedia = JSON.parse(body);
+ bodyMedia.question = msg.body ?? dataMessage.media?.[0].mime;
+ bodyMedia.uploads = dataMessage.media;
+ body = JSON.stringify(bodyMedia);
+ }
+
+ // await fs.writeFile(path.join(process.cwd(), 'webhook.json'), body);
+
const res = await fetch(hook.url, {
method: hook.method,
headers: {
@@ -244,56 +272,58 @@ async function handleIncomingMessage(msg: WAWebJS.Message) {
body,
});
- if (!res.ok) log(`⚠️ Webhook ${hook.url} gagal: ${res.status}`);
- const responseJson = await res.json();
+ const responseText = await res.text();
+
+ if (!res.ok) {
+ log(`⚠️ Webhook ${hook.url} gagal: ${res.status}`);
+ log(responseText);
+ await msg.reply("Maaf, terjadi kesalahan saat memproses pesan Anda [ERR01]");
+ return;
+ }
+
+ const responseJson = JSON.parse(responseText);
if (hook.replay) {
try {
- // === Simulasikan sedang mengetik ===
- const chat = await msg.getChat();
- await chat.sendStateTyping(); // tampilkan status 'sedang mengetik...'
-
- // Durasi delay tergantung panjang teks (lebih panjang = lebih lama)
const textResponseRaw = hook.replayKey
? getValueByPath(responseJson, hook.replayKey, JSON.stringify(responseJson))
: JSON.stringify(responseJson, null, 2);
- const typingDelay = Math.min(5000, Math.max(1500, textResponseRaw.length * 20)); // 1.5–5 detik
- await new Promise((resolve) => setTimeout(resolve, typingDelay));
+ const typingDelay = Math.min(5000, Math.max(1500, textResponseRaw.length * 20));
+ await new Promise((r) => setTimeout(r, typingDelay));
- // Setelah delay, hentikan typing indicator
- await chat.clearState(); // hilangkan status "mengetik..."
-
- // Kirim balasan ke pengirim
- await msg.reply(textResponseRaw);
+ await chat.clearState();
+ // send message
+ await chat.sendMessage(textResponseRaw);
log(`💬 Balasan dikirim ke ${msg.from} setelah mengetik selama ${typingDelay}ms`);
} catch (err) {
log('⚠️ Gagal menampilkan status mengetik:', err);
- await msg.reply(hook.replayKey
- ? getValueByPath(responseJson, hook.replayKey, JSON.stringify(responseJson))
- : JSON.stringify(responseJson, null, 2)
- );
+ await msg.reply("Maaf, terjadi kesalahan saat memproses pesan Anda [ERR03]");
}
}
-
} catch (err) {
log(`❌ Gagal kirim ke ${hook.url}:`, err);
+ await msg.reply("Maaf, terjadi kesalahan saat memproses pesan Anda [ERR04]");
}
})
);
-
} catch (error) {
- console.log(error);
+ log('❌ Error mengirim webhook:', error);
+ await msg.reply("Maaf, terjadi kesalahan saat memproses pesan Anda [ERR05]");
}
} catch (err) {
log('❌ Error handling pesan:', err);
+ await msg.reply("Maaf, terjadi kesalahan saat memproses pesan Anda [ERR06]");
+ } finally {
+ await chat.clearState();
}
}
+
function payloadConverter({ payload, data }: { payload: string; data: DataMessage }) {
try {
- const map: Record = {
+ const map: Record = {
'data.from': data.from,
'data.fromNumber': data.fromNumber,
'data.fromMe': data.fromMe,
@@ -303,19 +333,30 @@ function payloadConverter({ payload, data }: { payload: string; data: DataMessag
'data.to': data.to,
'data.deviceType': data.deviceType,
'data.notifyName': data.notifyName,
- 'data.media.data': data.media?.data ?? null,
- 'data.media.mimetype': data.media?.mimetype ?? null,
- 'data.media.filename': data.media?.filename ?? null,
- 'data.media.filesize': data.media?.filesize ?? 0,
+ 'data.media': data.media
};
let result = payload;
+
for (const [key, value] of Object.entries(map)) {
- result = result.replace(new RegExp(`{{\\s*${key}\\s*}}`, 'g'), String(value ?? ''));
+ let safeValue: string;
+
+ if (value === null || value === undefined) {
+ safeValue = '';
+ } else if (typeof value === 'object') {
+ // Perbaikan di sini — objek seperti media dikonversi ke JSON string
+ safeValue = JSON.stringify(value);
+ } else {
+ safeValue = String(value);
+ }
+
+ result = result.replace(new RegExp(`{{\\s*${key}\\s*}}`, 'g'), safeValue);
}
+
return result;
- } catch {
- return JSON.stringify(data, null, 2);
+ } catch (err) {
+ console.error("⚠️ payloadConverter error:", err);
+ return JSON.stringify(data);
}
}
diff --git a/src/server/lib/wa/wa_service.txt b/src/server/lib/wa/wa_service.txt
new file mode 100644
index 0000000..12ef459
--- /dev/null
+++ b/src/server/lib/wa/wa_service.txt
@@ -0,0 +1,343 @@
+import WAWebJS, { Client, LocalAuth, MessageMedia } from 'whatsapp-web.js';
+import qrcode from 'qrcode-terminal';
+import fs from 'fs/promises';
+import path from 'path';
+import { v4 as uuid } from 'uuid';
+import { prisma } from '../prisma';
+import { getValueByPath } from '../get_value_by_path';
+
+// === KONFIGURASI UTAMA ===
+const MEDIA_DIR = path.join(process.cwd(), 'downloads');
+await ensureDir(MEDIA_DIR);
+
+type DataMessage = {
+ from: string;
+ fromNumber: string;
+ fromMe: boolean;
+ body: string;
+ hasMedia: boolean;
+ type: WAWebJS.MessageTypes;
+ to: string;
+ deviceType: string;
+ media: {
+ data: WAWebJS.MessageMedia["data"];
+ mimetype: WAWebJS.MessageMedia["mimetype"];
+ filename: WAWebJS.MessageMedia["filename"];
+ filesize: WAWebJS.MessageMedia["filesize"];
+ };
+ notifyName: string;
+}
+
+// === STATE GLOBAL ===
+const state = {
+ client: null as Client | null,
+ reconnectTimeout: null as NodeJS.Timeout | null,
+ isReconnecting: false,
+ isStarting: false,
+ qr: null as string | null,
+ ready: false,
+ async restart() {
+ log('🔄 Restart manual diminta...');
+ await destroyClient();
+ await startClient();
+ },
+
+ async forceStart() {
+ log('⚠️ Force start — menghapus cache dan session auth...');
+ await destroyClient();
+ await safeRm("./.wwebjs_auth");
+ await safeRm("./wwebjs_cache");
+ await startClient();
+ },
+ async stop() {
+ log('🛑 Stop manual diminta...');
+ await destroyClient();
+ },
+};
+
+// === UTIL ===
+function log(...args: any[]) {
+ console.log(`[${new Date().toISOString()}]`, ...args);
+}
+
+async function ensureDir(dir: string) {
+ try {
+ await fs.access(dir);
+ } catch {
+ await fs.mkdir(dir, { recursive: true });
+ }
+}
+
+async function safeRm(path: string) {
+ try {
+ await fs.rm(path, { recursive: true, force: true });
+ } catch (err) {
+ log(`⚠️ Gagal hapus ${path}:`, err);
+ }
+}
+
+// === CLEANUP CLIENT ===
+async function destroyClient() {
+ if (state.reconnectTimeout) {
+ clearTimeout(state.reconnectTimeout);
+ state.reconnectTimeout = null;
+ }
+ if (state.client) {
+ try {
+ state.client.removeAllListeners();
+ await state.client.destroy();
+ log('🧹 Client lama dihentikan & listener dibersihkan');
+ } catch (err) {
+ log('⚠️ Gagal destroy client:', err);
+ }
+ state.client = null;
+ state.ready = false;
+ }
+}
+
+// === PEMBUATAN CLIENT ===
+async function startClient() {
+ if (state.isStarting || state.isReconnecting) {
+ log('⏳ startClient diabaikan — proses sedang berjalan...');
+ return;
+ }
+ state.isStarting = true;
+
+ await destroyClient();
+
+ log('🚀 Memulai WhatsApp client...');
+ const client = new Client({
+ authStrategy: new LocalAuth({
+ dataPath: path.join(process.cwd(), '.wwebjs_auth'),
+ }),
+ puppeteer: {
+ headless: true,
+ args: [
+ '--no-sandbox',
+ '--disable-setuid-sandbox',
+ '--disable-dev-shm-usage',
+ '--disable-gpu',
+ ],
+ },
+ });
+
+ state.client = client;
+
+ // === EVENT LISTENERS ===
+ client.on('qr', (qr) => {
+ state.qr = qr;
+ qrcode.generate(qr, { small: true });
+ log('🔑 QR code baru diterbitkan');
+ });
+
+ client.on('ready', () => {
+ log('✅ WhatsApp client siap digunakan!');
+ state.ready = true;
+ state.isReconnecting = false;
+ state.isStarting = false;
+ state.qr = null;
+ if (state.reconnectTimeout) {
+ clearTimeout(state.reconnectTimeout);
+ state.reconnectTimeout = null;
+ }
+ });
+
+ client.on('auth_failure', (msg) => {
+ log('❌ Autentikasi gagal:', msg);
+ state.ready = false;
+ });
+
+ client.on('disconnected', async (reason) => {
+ log('⚠️ Client terputus:', reason);
+ state.ready = false;
+
+ if (state.reconnectTimeout) clearTimeout(state.reconnectTimeout);
+ log('⏳ Mencoba reconnect dalam 5 detik...');
+
+ state.reconnectTimeout = setTimeout(async () => {
+ state.isReconnecting = false;
+ await startClient();
+ }, 5000);
+ });
+
+ client.on('message', handleIncomingMessage);
+
+ // === INISIALISASI ===
+ try {
+ await client.initialize();
+ } catch (err) {
+ log('❌ Gagal inisialisasi client:', err);
+ log('⏳ Mencoba reconnect dalam 10 detik...');
+ state.reconnectTimeout = setTimeout(async () => {
+ state.isReconnecting = false;
+ await startClient();
+ }, 10000);
+ } finally {
+ state.isStarting = false;
+ }
+}
+
+// === HANDLER PESAN MASUK ===
+async function handleIncomingMessage(msg: WAWebJS.Message) {
+ log(`💬 Pesan dari ${msg.from}: ${msg.body || '[MEDIA]'}`);
+ if (msg.from.endsWith('@g.us') || msg.isStatus || msg.from === 'status@broadcast') {
+ log(`🚫 Pesan dari grup/status diabaikan (${msg.from})`);
+ return;
+ }
+
+ try {
+
+ const body = msg.body?.toLowerCase().trim() || '';
+ const notifyName = (msg as any)._data.notifyName;
+
+ const dataMessage: DataMessage = {
+ from: msg.from,
+ fromNumber: msg.from.split('@')[0] || '',
+ fromMe: msg.fromMe,
+ body: msg.body,
+ hasMedia: msg.hasMedia,
+ type: msg.type,
+ to: msg.to,
+ deviceType: msg.deviceType,
+ media: {
+ data: null as unknown as WAWebJS.MessageMedia['data'],
+ mimetype: null as unknown as WAWebJS.MessageMedia['mimetype'],
+ filename: null as unknown as WAWebJS.MessageMedia['filename'],
+ filesize: null as unknown as WAWebJS.MessageMedia['filesize'],
+
+ },
+ notifyName,
+ };
+
+ // Media handler
+ if (msg.hasMedia) {
+ const media = await msg.downloadMedia();
+
+ dataMessage.media = {
+ data: media.data,
+ mimetype: media.mimetype,
+ filename: media.filename,
+ filesize: media.filesize
+ };
+ }
+
+ // to web hook
+ try {
+ const webhooks = await prisma.webHook.findMany({ where: { enabled: true } });
+
+ if (!webhooks.length) {
+ log('🚫 Tidak ada webhook yang aktif');
+ return;
+ }
+
+ await Promise.allSettled(
+ webhooks.map(async (hook) => {
+ try {
+ console.log("send webhook " + hook.url);
+ const body = payloadConverter({ payload: hook.payload ?? JSON.stringify(dataMessage), data: dataMessage });
+ const res = await fetch(hook.url, {
+ method: hook.method,
+ headers: {
+ ...(JSON.parse(hook.headers ?? '{}') as Record),
+ ...(hook.apiToken ? { Authorization: `Bearer ${hook.apiToken}` } : {}),
+ },
+ body,
+ });
+
+ if (!res.ok) log(`⚠️ Webhook ${hook.url} gagal: ${res.status}`);
+ const responseJson = await res.json();
+
+ if (hook.replay) {
+ try {
+ // === Simulasikan sedang mengetik ===
+ const chat = await msg.getChat();
+ await chat.sendStateTyping(); // tampilkan status 'sedang mengetik...'
+
+ // Durasi delay tergantung panjang teks (lebih panjang = lebih lama)
+ const textResponseRaw = hook.replayKey
+ ? getValueByPath(responseJson, hook.replayKey, JSON.stringify(responseJson))
+ : JSON.stringify(responseJson, null, 2);
+
+ const typingDelay = Math.min(5000, Math.max(1500, textResponseRaw.length * 20)); // 1.5–5 detik
+ await new Promise((resolve) => setTimeout(resolve, typingDelay));
+
+ // Setelah delay, hentikan typing indicator
+ await chat.clearState(); // hilangkan status "mengetik..."
+
+ // Kirim balasan ke pengirim
+ await msg.reply(textResponseRaw);
+
+ log(`💬 Balasan dikirim ke ${msg.from} setelah mengetik selama ${typingDelay}ms`);
+ } catch (err) {
+ log('⚠️ Gagal menampilkan status mengetik:', err);
+ await msg.reply(hook.replayKey
+ ? getValueByPath(responseJson, hook.replayKey, JSON.stringify(responseJson))
+ : JSON.stringify(responseJson, null, 2)
+ );
+ }
+ }
+
+ } catch (err) {
+ log(`❌ Gagal kirim ke ${hook.url}:`, err);
+ }
+ })
+ );
+
+ } catch (error) {
+ console.log(error);
+ }
+ } catch (err) {
+ log('❌ Error handling pesan:', err);
+ }
+}
+
+function payloadConverter({ payload, data }: { payload: string; data: DataMessage }) {
+ try {
+ const map: Record = {
+ 'data.from': data.from,
+ 'data.fromNumber': data.fromNumber,
+ 'data.fromMe': data.fromMe,
+ 'data.body': data.body,
+ 'data.hasMedia': data.hasMedia,
+ 'data.type': data.type,
+ 'data.to': data.to,
+ 'data.deviceType': data.deviceType,
+ 'data.notifyName': data.notifyName,
+ 'data.media.data': data.media?.data ?? null,
+ 'data.media.mimetype': data.media?.mimetype ?? null,
+ 'data.media.filename': data.media?.filename ?? null,
+ 'data.media.filesize': data.media?.filesize ?? 0,
+ };
+
+ let result = payload;
+ for (const [key, value] of Object.entries(map)) {
+ result = result.replace(new RegExp(`{{\\s*${key}\\s*}}`, 'g'), String(value ?? ''));
+ }
+ return result;
+ } catch {
+ return JSON.stringify(data, null, 2);
+ }
+}
+
+
+// === CLEANUP SAAT EXIT ===
+process.on('SIGINT', async () => {
+ log('🛑 SIGINT diterima, menutup client...');
+ await destroyClient();
+ process.exit(0);
+});
+
+process.on('SIGTERM', async () => {
+ log('🛑 SIGTERM diterima, menutup client...');
+ await destroyClient();
+ process.exit(0);
+});
+
+
+const getState = () => state;
+
+export { startClient, destroyClient, getState };
+
+if (import.meta.main) {
+ await startClient();
+}
diff --git a/webhook.json b/webhook.json
new file mode 100644
index 0000000..691904d
--- /dev/null
+++ b/webhook.json
@@ -0,0 +1,14 @@
+{
+ "question": "ini",
+ "overrideConfig": {
+ "sessionId": "jenna ai_x_6289505046093"
+ },
+ "uploads": [
+ {
+ "type": "file:full",
+ "data": "data:application/pdf;base64,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CjAKMTU1ClsKMzg2Cl0KMTU2CjE1OAowCjE1OQpbCjMwNgo0OTgKOTA1CjQ5OAowCjAKMzAzCjMwMwpdCjE2NwoxNzQKMAoxNzUKWwo0OTgKMAowCjY4MgpdCjE3OQoxOTAKMAoxOTEKMjAyCjUwNgoyMDMKMjIxCjAKMjIyClsKNDk4CjAKMAo0OTgKXQpdCj4+CmVuZG9iagozMAowCm9iago8PAovVHlwZQovRm9udERlc2NyaXB0b3IKL0ZvbnROYW1lCi9NVUZVWlkrQ2FsaWJyaQovRmxhZ3MKNAovRm9udEJCb3gKWwotOTcKLTE5Mwo4NTkKODQ2Cl0KL0FzY2VudAo3NTAKL0Rlc2NlbnQKLTI1MAovSXRhbGljQW5nbGUKMAovQ2FwSGVpZ2h0CjYzMQovU3RlbVYKODAKL0ZvbnRGaWxlMgozMQowClIKPj4KZW5kb2JqCjMyCjAKb2JqCjQzNAplbmRvYmoKMzMKMApvYmoKMTMwMjEKZW5kb2JqCjM0CjAKb2JqCjQ5OQplbmRvYmoKMzUKMApvYmoKMTkwMTYKZW5kb2JqCjEKMApvYmoKPDwKL1R5cGUKL1BhZ2VzCi9LaWRzClsKNQowClIKMTQKMApSCjE5CjAKUgpdCi9Db3VudAozCj4+CmVuZG9iagp4cmVmCjAgMzYKMDAwMDAwMDAwMiA2NTUzNSBmIAowMDAwMDQ4MTMzIDAwMDAwIG4gCjAwMDAwMDAwMDAgMDAwMDAgZiAKMDAwMDAwMDAxNiAwMDAwMCBuIAowMDAwMDAwMTQyIDAwMDAwIG4gCjAwMDAwMDAyMjkgMDAwMDAgbiAKMDAwMDAwMDM5NCAwMDAwMCBuIAowMDAwMDEyMDkwIDAwMDAwIG4gCjAwMDAwMDUxODMgMDAwMDAgbiAKMDAwMDAwNTIwMyAwMDAwMCBuIAowMDAwMDEyMDAwIDAwMDAwIG4gCjAwMDAwMTIwNTIgMDAwMDAgbiAKMDAwMDAxMjYyMCAwMDAwMCBuIAowMDAwMDEyNzY5IDAwMDAwIG4gCjAwMDAwMDUyMjIgMDAwMDAgbiAKMDAwMDAwNTM5MSAwMDAwMCBuIAowMDAwMDEyMjc2IDAwMDAwIG4gCjAwMDAwMTAwNTEgMDAwMDAgbiAKMDAwMDAxMDA3MiAwMDAwMCBuIAowMDAwMDEwMDkyIDAwMDAwIG4gCjAwMDAwMTAyNjEgMDAwMDAgbiAKMDAwMDAxMjQ0OCAwMDAwMCBuIAowMDAwMDExOTU5IDAwMDAwIG4gCjAwMDAwMTE5ODAgMDAwMDAgbiAKMDAwMDAyNjUyMCAwMDAwMCBuIAowMDAwMDEyOTEzIDAwMDAwIG4gCjAwMDAwMjcxOTEgMDAwMDAgbiAKMDAwMDAxMzQyMyAwMDAwMCBuIAowMDAwMDQ3MDU4IDAwMDAwIG4gCjAwMDAwMjczOTEgMDAwMDAgbiAKMDAwMDA0Nzg1NSAwMDAwMCBuIAowMDAwMDI3OTY2IDAwMDAwIG4gCjAwMDAwNDgwNDkgMDAwMDAgbiAKMDAwMDA0ODA2OSAwMDAwMCBuIAowMDAwMDQ4MDkxIDAwMDAwIG4gCjAwMDAwNDgxMTEgMDAwMDAgbiAKdHJhaWxlcgo8PAovU2l6ZQozNgovUm9vdAozCjAKUgovSW5mbwo0CjAKUgo+PgpzdGFydHhyZWYKNDgyMDYKJSVFT0YK",
+ "mime": "application/pdf",
+ "name": "Dataset_Potensi_Desa.pdf"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/x.sh b/x.sh
new file mode 100644
index 0000000..bb80b7b
--- /dev/null
+++ b/x.sh
@@ -0,0 +1,8 @@
+
+#!/bin/bash
+TOKEN="EAALP22EWyC4BPv7XnK1xSaZCWccblEoJFbHzPZAf5mlp4678lSM7cqhQl1ExATf8abrOpinvvFF6U6ruK2FsJqIk8wg6DiUz2fc0NYfcwjon3ng7I3C5HSDQHecgTiJLUBxfZAcvE4IIlhks722jakXaJpojlByo8QJ0CEURtzwEU1guFq7YTX3Et0ZCkbhkdftZCOGmpUKFjL5w5nUdd26Nd58YrLVZCoT8NKhxpWFQZDZD"
+curl -i -X POST \
+ https://graph.facebook.com/v22.0/838757782652201/messages \
+ -H 'Authorization: Bearer $TOKEN' \
+ -H 'Content-Type: application/json' \
+ -d '{ "messaging_product": "whatsapp", "to": "6289505046093", "type": "template", "template": { "name": "hello_world", "language": { "code": "en_US" } } }'
\ No newline at end of file
diff --git a/x.ts b/x.ts
index 1475f06..f10e4fb 100644
--- a/x.ts
+++ b/x.ts
@@ -1,73 +1,33 @@
+async function query(data: any) {
-/**
- * Helper type to recursively generate all possible key paths up to 7 levels deep.
- * Example: "media.data", "a.b.c.d.e.f.g"
- */
- type NestedKeyOf = {
- [K in keyof T & (string | number)]: T[K] extends Record
- ? | `${Prev}${K}`
- | `${Prev}${K}.${NestedKeyOf}`
- : `${Prev}${K}`;
- }[keyof T & (string | number)];
-
- /**
- * Safely get deep value by string path like "a.b.c[0].d"
- */
- function getValueByPath<
- T extends object,
- P extends string,
- R = unknown
- >(obj: T, path: P, defaultValue?: R): any {
- try {
- return path
- .replace(/\[(\w+)\]/g, '.$1')
- .split('.')
- .reduce((acc: any, key) => (acc != null ? acc[key] : undefined), obj) ?? defaultValue;
- } catch {
- return defaultValue;
- }
+ const file = Buffer.from(await Bun.file("./downloads/billing-server-20-06-2024.pdf").arrayBuffer()).toString("base64");
+ const base64File = `data:application/pdf;base64,${file}`;
+
+ const fileObject = {
+ type: "file:full",
+ data: base64File,
+ mime: "application/pdf",
+ name: "billing-server-20-06-2024.pdf"
}
-
- /**
- * Safely set deep value by string path like "a.b.c[0].d"
- */
- export function setValueByPath(
- obj: T,
- path: string,
- value: any
- ): void {
- const keys = path.replace(/\[(\w+)\]/g, '.$1').split('.');
- let current: any = obj;
-
- for (let i = 0; i < keys.length - 1; i++) {
- const key = keys[i];
- if (current[key as keyof typeof current] == null || typeof current[key as keyof typeof current] !== 'object') {
- current[key as keyof typeof current] = isNaN(Number(keys[i + 1])) ? {} : [];
+ const response = await fetch(
+ "https://cloud-aiflow.wibudev.com/api/v1/prediction/4da85628-c638-43d3-9491-4cd0a7e6b1b8",
+ {
+ headers: {
+ Authorization: "Bearer v3WdPjn61bNDsEYCO5_LYPRs16ICKjpQE6lF60DjpNo",
+ "Content-Type": "application/json"
+ },
+ method: "POST",
+ body: JSON.stringify({
+ ...data,
+ uploads: [fileObject]
+ })
}
- current = current[key as keyof typeof current];
- }
-
- current[keys[keys.length - 1] as keyof typeof current] = value;
- }
-
+ );
+ const result = await response.text();
+ return result;
+}
- const data = {
- "from": "6289505046093@c.us",
- "fromMe": false,
- "body": "halo gaes",
- "hasMedia": false,
- "type": "chat",
- "to": "6289697338821@c.us",
- "deviceType": "android",
- "media": {
- "data": "image...",
- "mimetype": null,
- "filename": null,
- "filesize": null
- },
- "notifyName": "jenna ai"
- }
- const find = getValueByPath(data, "media.data")
-
- console.log(find)
\ No newline at end of file
+query({"question": "apa isi data ini ?"}).then((response) => {
+ console.log(response);
+});