From 05b2b081c2ebe8f61cc8f65c2ebc87747dd55a36 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 23 Aug 2022 20:43:29 -0500 Subject: [PATCH 01/33] Update Dockerfile --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 82a64e2..39c4b9d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,4 +12,6 @@ COPY . . RUN npm install -g typescript ts-node -CMD [ "ts-node", "index.ts" ] \ No newline at end of file +CMD [ "ts-node", "index.ts" ] + +LABEL org.opencontainers.image.source="https://github.com/llisaeva/CSSC-Bot" \ No newline at end of file From 9c74494a00705df554d57eedfd47412129a86ddb Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 23 Aug 2022 21:30:45 -0500 Subject: [PATCH 02/33] Add License --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1a984ca --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Lisa Isaeva + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 6df16b8574f742b96d481881ce80acc1637fe985 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 23 Aug 2022 21:31:06 -0500 Subject: [PATCH 03/33] Add cs class list --- COMPSCI-Fall-Class-List.json | 237 +++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 COMPSCI-Fall-Class-List.json diff --git a/COMPSCI-Fall-Class-List.json b/COMPSCI-Fall-Class-List.json new file mode 100644 index 0000000..94a7bbd --- /dev/null +++ b/COMPSCI-Fall-Class-List.json @@ -0,0 +1,237 @@ +[ + { + "code": "COMPSCI 150", + "title": "Survey of Computer Science", + "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." + }, + { + "code": "COMPSCI 202", + "title": "Introductory Programming Using Python", + "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." + }, + { + "code": "COMPSCI 250", + "title": "Introductory Computer Programming", + "info": "Programming in Python. Basic control structures including recursion. Basic and library data types. Problem solving with objects. Writing classes. Basic software development skills.\n\nCounts as repeat of CompSci 290 with similar topic. Pre-req: Level 30 on Math Placement Test, or a grade of C or better in Math 105 or 108." + }, + { + "code": "COMPSCI 251", + "title": "Intermediate Computer Programming", + "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." + }, + { + "code": "COMPSCI 317", + "title": "Discrete Information Structures", + "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." + }, + { + "code": "COMPSCI 337", + "title": "System Programming", + "info": "Introduction to the application programmer interface for a modern operating system. Overview of mechanisms for object oriented programming and memory management\n\nPrereq: C or better in CompSci 251(P)" + }, + { + "code": "COMPSCI 351", + "title": "Data Structures and Algorithms", + "info": "Programming in a structured, high-level, object-oriented language. Implementation of data structures and algorithms and their application.\n\nPrereq: Math Placement Level 40 or Math 116(P) or 211(P); C or better in CompSci 251(P)." + }, + { + "code": "COMPSCI 361", + "title": "Introduction to Software Engineering", + "info": "Introduction to core topics of software engineering including requirements analysis, object-oriented design, testing, and project management. Overview of ethical and social issues in computing.\n\nPrereq: C or better in CompSci 351(P), satisfaction of GER English Composition competency req." + }, + { + "code": "COMPSCI 423", + "title": "Introduction to Natural Language Processing", + "info": "Introduction to natural language processing programs and an overview of the field. Topics include syntactic frameworks, parsing, semantics, interpretation, and applications.\n\nPrereq: jr st; C or better in CompSci 351(P)." + }, + { + "code": "COMPSCI 431", + "title": "Programming Languages Concepts", + "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." + }, + { + "code": "COMPSCI 431G", + "title": "Programming Languages Concepts", + "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." + }, + { + "code": "COMPSCI 458", + "title": "Computer Architecture", + "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." + }, + { + "code": "COMPSCI 458G", + "title": "Computer Architecture", + "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." + }, + { + "code": "COMPSCI 481", + "title": "Server-side Internet Programming", + "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." + }, + { + "code": "COMPSCI 481G", + "title": "Server-side Internet Programming", + "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." + }, + { + "code": "COMPSCI 520", + "title": "Computer Networks", + "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." + }, + { + "code": "COMPSCI 520G", + "title": "Computer Networks", + "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." + }, + { + "code": "COMPSCI 535", + "title": "Algorithm Design and Analysis", + "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." + }, + { + "code": "COMPSCI 535G", + "title": "Algorithm Design and Analysis", + "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." + }, + { + "code": "COMPSCI 537", + "title": "Introduction to Operating Systems", + "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." + }, + { + "code": "COMPSCI 537G", + "title": "Introduction to Operating Systems", + "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." + }, + { + "code": "COMPSCI 552", + "title": "Advanced Object-Oriented Programming", + "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." + }, + { + "code": "COMPSCI 552G", + "title": "Advanced Object-Oriented Programming", + "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." + }, + { + "code": "COMPSCI 594", + "title": "Capstone Project Preparation", + "info": "Student teams will develop requirements and functionality specifications for their capstone projects and conduct the necessary research on the prior art and technologies to be used.\n\nMeant to be taken in the semester immediately prior to the one in which the student will take COMPSCI 595. Prereq: senior standing." + }, + { + "code": "COMPSCI 595", + "title": "Capstone Project", + "info": "Students will integrate their knowledge of the undergraduate computer science curriculum by implementing a significant computer science team project.\n\nPrereq: senior standing, COMPSCI 351(P), COMPSCI 361(P), COMPSCI 594(P) and credit in at least 6 credits of 400 or higher COMPSCI or ELECENG courses." + }, + { + "code": "COMPSCI 599", + "title": "Senior Thesis", + "info": "Independent scholarly research in Computer Science supervised by a faculty member.\n\nPrereq: sr st & cons instr." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: 3D Graphics", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Cloud Computing", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Concurrent Programming", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Database Security", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Introduction to Research Computing", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 699", + "title": "Independent Study", + "info": "May be retaken to max of 6 cr by undergraduates. Prereq: jr st; cons instr." + }, + { + "code": "COMPSCI 720", + "title": "Computational Models of Decision Making", + "info": "Theoretical foundations and practical problems of formulating and constructing computational models of decision making.\n\nPrereq: basic course in Probability or Statistics." + }, + { + "code": "COMPSCI 723", + "title": "Natural Language Processing", + "info": "Principles and problems of natural language processing with emphasis on recent advances and open problems. Topics: lexicons, parsing, interpretation, discourse structure, generation, and collaborative interfaces.\n\nNot open to students with cr in CompSci 423. Prereq: grad st; CompSci 422(P) or 710(P)." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: 3D Graphics", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Cloud Computing", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Concurrent Programming", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Database Security", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Introduction to Research Computing", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 870", + "title": "Medical Informatics Seminar", + "info": "Presentations by medical informatics affiliated faculty and invited speakers. Graduate students may present their work or published research from recent medical informatics journals or conferences.\n\nMeets once every two weeks for 100 minutes. Prereq: grad st." + }, + { + "code": "COMPSCI 888", + "title": "Candidate for Degree", + "info": "Available for graduate students who must meet minimum credit load requirement.\n\nFee for 1 cr assessed; unit does not count towards credit load for Fin Aid. Repeatable. Satisfactory/Unsatisfactory only. Prereq: graduate standing." + }, + { + "code": "COMPSCI 990", + "title": "Masters Thesis", + "info": "Prereq: grad st; cons instr." + }, + { + "code": "COMPSCI 995", + "title": "Master's Capstone Project", + "info": "Independent project supervised by student's adviser\n\nPrereq: grad st; cons instr & grad prog comm." + }, + { + "code": "COMPSCI 998", + "title": "Doctoral Thesis", + "info": "Prereq: grad st; cons instr & grad prog committee." + }, + { + "code": "COMPSCI 999", + "title": "Advanced Independent Study", + "info": "Prereq: grad st; cons instr & grad prog comm." + } +] \ No newline at end of file From 50142a5e4a14550e43023f1d608fec1564df23bd Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Wed, 24 Aug 2022 09:12:43 -0500 Subject: [PATCH 04/33] Transfer to Organization --- Dockerfile | 2 +- README.md | 9 +++++++-- commands/user/github.ts | 2 +- features/status-changer.ts | 2 +- package.json | 6 +++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 39c4b9d..5864e01 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,4 +14,4 @@ RUN npm install -g typescript ts-node CMD [ "ts-node", "index.ts" ] -LABEL org.opencontainers.image.source="https://github.com/llisaeva/CSSC-Bot" \ No newline at end of file +LABEL org.opencontainers.image.source="https://github.com/Antares-Network/CSSC-Bot" \ No newline at end of file diff --git a/README.md b/README.md index cda4964..92d7cc6 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Follow this link in a browser, and choose the private server you created to add ### Run from source ```bash -git clone https://github.com/llisaeva/CSSC-Bot.git +git clone https://github.com/Antares-Network/CSSC-Bot.git # Fill out the .env file using the template in .env.template npm install npm install -g typescript ts-node @@ -70,7 +70,7 @@ ts-node index.ts ### Run from Docker ```bash -git clone https://github.com/llisaeva/CSSC-Bot.git +git clone https://github.com/Antares-Network/CSSC-Bot.git # Fill out the .env file using the template in .env.template; # Or add the environment variables to your docker run command by adding the # --env-file .env option @@ -119,3 +119,8 @@ The bot should become responsive. You can check for errors in the console. - [WOKcommands Docs](https://docs.wornoffkeys.com/) - [AntaresBot Codebase](https://playantares.com/antaresbot) - [Antares Status Tracking](https://status.playantares.com/) + +## Credits + +- [Lisa Isaeva](https://github.com/llisaeva) +- [Nate Goldsborough](https://github.com/nathen418) \ No newline at end of file diff --git a/commands/user/github.ts b/commands/user/github.ts index d8e200b..7041b4a 100644 --- a/commands/user/github.ts +++ b/commands/user/github.ts @@ -16,7 +16,7 @@ export default { const color = "#0099ff"; const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; const title = "Github"; - const description = "Click here to go to the CSSC-bot repo: \n https://github.com/llisaeva/CSSC-Bot"; + const description = "Click here to go to the CSSC-bot repo: \n https://github.com/Antares-Network/CSSC-Bot"; const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; diff --git a/features/status-changer.ts b/features/status-changer.ts index 6ae2e93..0d0cd9f 100644 --- a/features/status-changer.ts +++ b/features/status-changer.ts @@ -9,7 +9,7 @@ export default async (client: Client) => { `status.playantares.com`, `playantares.com/github`, `status.playantares.com`, - `Antares Network Hosting`, + `Antares Network Server Hosting`, 'Go to #roles!', 'Hello! I\'m CSSC-Bot', diff --git a/package.json b/package.json index 8f6b992..dd50d0f 100644 --- a/package.json +++ b/package.json @@ -11,14 +11,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/llisaeva/CSSC-Bot.git" + "url": "git+https://github.com/Antares-Network/CSSC-Bot.git" }, "author": "llisaeva, nathen418", "license": "ISC", "bugs": { - "url": "https://github.com/llisaeva/CSSC-Bot/issues" + "url": "https://github.com/Antares-Network/CSSC-Bot/issues" }, - "homepage": "https://github.com/llisaeva/CSSC-Bot#readme", + "homepage": "https://github.com/Antares-Network/CSSC-Bot#readme", "dependencies": { "axios": "^0.27.2", "chalk": "^4.1.2", From 622ffbf761856649b77aec2e2a001bfc1c25bccf Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Thu, 25 Aug 2022 00:43:59 -0500 Subject: [PATCH 05/33] Adding csClasses command, broken code do not use --- COMPSCI-Fall-Class-List.json | 237 ---------------------------------- commands/owner/csClassPoll.ts | 108 ++++++++++++++++ csClasses.ts | 192 +++++++++++++++++++++++++++ index.ts | 2 +- tsconfig.json | 2 +- 5 files changed, 302 insertions(+), 239 deletions(-) delete mode 100644 COMPSCI-Fall-Class-List.json create mode 100644 commands/owner/csClassPoll.ts create mode 100644 csClasses.ts diff --git a/COMPSCI-Fall-Class-List.json b/COMPSCI-Fall-Class-List.json deleted file mode 100644 index 94a7bbd..0000000 --- a/COMPSCI-Fall-Class-List.json +++ /dev/null @@ -1,237 +0,0 @@ -[ - { - "code": "COMPSCI 150", - "title": "Survey of Computer Science", - "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." - }, - { - "code": "COMPSCI 202", - "title": "Introductory Programming Using Python", - "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." - }, - { - "code": "COMPSCI 250", - "title": "Introductory Computer Programming", - "info": "Programming in Python. Basic control structures including recursion. Basic and library data types. Problem solving with objects. Writing classes. Basic software development skills.\n\nCounts as repeat of CompSci 290 with similar topic. Pre-req: Level 30 on Math Placement Test, or a grade of C or better in Math 105 or 108." - }, - { - "code": "COMPSCI 251", - "title": "Intermediate Computer Programming", - "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." - }, - { - "code": "COMPSCI 317", - "title": "Discrete Information Structures", - "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." - }, - { - "code": "COMPSCI 337", - "title": "System Programming", - "info": "Introduction to the application programmer interface for a modern operating system. Overview of mechanisms for object oriented programming and memory management\n\nPrereq: C or better in CompSci 251(P)" - }, - { - "code": "COMPSCI 351", - "title": "Data Structures and Algorithms", - "info": "Programming in a structured, high-level, object-oriented language. Implementation of data structures and algorithms and their application.\n\nPrereq: Math Placement Level 40 or Math 116(P) or 211(P); C or better in CompSci 251(P)." - }, - { - "code": "COMPSCI 361", - "title": "Introduction to Software Engineering", - "info": "Introduction to core topics of software engineering including requirements analysis, object-oriented design, testing, and project management. Overview of ethical and social issues in computing.\n\nPrereq: C or better in CompSci 351(P), satisfaction of GER English Composition competency req." - }, - { - "code": "COMPSCI 423", - "title": "Introduction to Natural Language Processing", - "info": "Introduction to natural language processing programs and an overview of the field. Topics include syntactic frameworks, parsing, semantics, interpretation, and applications.\n\nPrereq: jr st; C or better in CompSci 351(P)." - }, - { - "code": "COMPSCI 431", - "title": "Programming Languages Concepts", - "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." - }, - { - "code": "COMPSCI 431G", - "title": "Programming Languages Concepts", - "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." - }, - { - "code": "COMPSCI 458", - "title": "Computer Architecture", - "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." - }, - { - "code": "COMPSCI 458G", - "title": "Computer Architecture", - "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." - }, - { - "code": "COMPSCI 481", - "title": "Server-side Internet Programming", - "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." - }, - { - "code": "COMPSCI 481G", - "title": "Server-side Internet Programming", - "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." - }, - { - "code": "COMPSCI 520", - "title": "Computer Networks", - "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." - }, - { - "code": "COMPSCI 520G", - "title": "Computer Networks", - "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." - }, - { - "code": "COMPSCI 535", - "title": "Algorithm Design and Analysis", - "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." - }, - { - "code": "COMPSCI 535G", - "title": "Algorithm Design and Analysis", - "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." - }, - { - "code": "COMPSCI 537", - "title": "Introduction to Operating Systems", - "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." - }, - { - "code": "COMPSCI 537G", - "title": "Introduction to Operating Systems", - "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." - }, - { - "code": "COMPSCI 552", - "title": "Advanced Object-Oriented Programming", - "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." - }, - { - "code": "COMPSCI 552G", - "title": "Advanced Object-Oriented Programming", - "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." - }, - { - "code": "COMPSCI 594", - "title": "Capstone Project Preparation", - "info": "Student teams will develop requirements and functionality specifications for their capstone projects and conduct the necessary research on the prior art and technologies to be used.\n\nMeant to be taken in the semester immediately prior to the one in which the student will take COMPSCI 595. Prereq: senior standing." - }, - { - "code": "COMPSCI 595", - "title": "Capstone Project", - "info": "Students will integrate their knowledge of the undergraduate computer science curriculum by implementing a significant computer science team project.\n\nPrereq: senior standing, COMPSCI 351(P), COMPSCI 361(P), COMPSCI 594(P) and credit in at least 6 credits of 400 or higher COMPSCI or ELECENG courses." - }, - { - "code": "COMPSCI 599", - "title": "Senior Thesis", - "info": "Independent scholarly research in Computer Science supervised by a faculty member.\n\nPrereq: sr st & cons instr." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: 3D Graphics", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Cloud Computing", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Concurrent Programming", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Database Security", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Introduction to Research Computing", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 699", - "title": "Independent Study", - "info": "May be retaken to max of 6 cr by undergraduates. Prereq: jr st; cons instr." - }, - { - "code": "COMPSCI 720", - "title": "Computational Models of Decision Making", - "info": "Theoretical foundations and practical problems of formulating and constructing computational models of decision making.\n\nPrereq: basic course in Probability or Statistics." - }, - { - "code": "COMPSCI 723", - "title": "Natural Language Processing", - "info": "Principles and problems of natural language processing with emphasis on recent advances and open problems. Topics: lexicons, parsing, interpretation, discourse structure, generation, and collaborative interfaces.\n\nNot open to students with cr in CompSci 423. Prereq: grad st; CompSci 422(P) or 710(P)." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: 3D Graphics", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Cloud Computing", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Concurrent Programming", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Database Security", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Introduction to Research Computing", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 870", - "title": "Medical Informatics Seminar", - "info": "Presentations by medical informatics affiliated faculty and invited speakers. Graduate students may present their work or published research from recent medical informatics journals or conferences.\n\nMeets once every two weeks for 100 minutes. Prereq: grad st." - }, - { - "code": "COMPSCI 888", - "title": "Candidate for Degree", - "info": "Available for graduate students who must meet minimum credit load requirement.\n\nFee for 1 cr assessed; unit does not count towards credit load for Fin Aid. Repeatable. Satisfactory/Unsatisfactory only. Prereq: graduate standing." - }, - { - "code": "COMPSCI 990", - "title": "Masters Thesis", - "info": "Prereq: grad st; cons instr." - }, - { - "code": "COMPSCI 995", - "title": "Master's Capstone Project", - "info": "Independent project supervised by student's adviser\n\nPrereq: grad st; cons instr & grad prog comm." - }, - { - "code": "COMPSCI 998", - "title": "Doctoral Thesis", - "info": "Prereq: grad st; cons instr & grad prog committee." - }, - { - "code": "COMPSCI 999", - "title": "Advanced Independent Study", - "info": "Prereq: grad st; cons instr & grad prog comm." - } -] \ No newline at end of file diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts new file mode 100644 index 0000000..9ee898a --- /dev/null +++ b/commands/owner/csClassPoll.ts @@ -0,0 +1,108 @@ +import chalk from "chalk"; +import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageActionRowComponent } from "discord.js"; +import { ICommand } from "wokcommands"; +import { checkForRoles } from "../../rolesOps"; +import csClassOptions from "../../csClasses"; + +export default { + name: "csClassPoll", + category: "owner", + description: "Posts the Cs Class Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, + + callback: async ({ client, interaction: msgInt }) => { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the option(s) with your current COMPSCI classes.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); + + + // Create some vars + let csClassOptionsChunks = []; + let lessThan25Row = new MessageActionRow() + let greaterThan25RowList: MessageActionRowComponent[] = []; + + // Check if csClassOptions is larger than 25 items + if (csClassOptions.length > 25) { + // Split csClassOptions into chunks of 25 + for (let i = 0; i < csClassOptions.length; i += 25) { + csClassOptionsChunks.push(csClassOptions.slice(i, i + 25)); + console.log(csClassOptions.slice(i, i + 25)) //! DEBUG + console.log("got here") //! DEBUG + } + } + // Loop through csClassOptionsChunks + for (let i = 0; i < csClassOptionsChunks.length; i++) { + // Loop through csClassOptionsChunks[i] + let menu = new MessageSelectMenu() + menu.setCustomId(`csClassPoll+${i}`) + console.log(`csClassPoll+${i}`) //! DEBUG + menu.setPlaceholder("Select an option") + lessThan25Row.addComponents(menu); + for (let j = 0; j < csClassOptionsChunks[i].length; j++) { + // Create row one of the buttons for the poll + menu.addOptions( + { + label: csClassOptionsChunks[i][j].label, + value: csClassOptionsChunks[i][j].label, + description: csClassOptionsChunks[i][j].description, + } + ) + } + greaterThan25RowList.push(menu); + } + + + // Check if greaterThan25RowList contains any items, and if it does, loop through greaterThan25RowList + if (greaterThan25RowList.length > 0) { + + // console.log(greaterThan25RowList) //! DEBUG + + for (let i = 0; i < greaterThan25RowList.length; i++) { + // Loop through greaterThan25RowList[i] + let row = new MessageActionRow() + row.addComponents(greaterThan25RowList[i]) + msgInt.channel!.send({ embeds: [infoEmbed], components: [row] }); + } + } else { + msgInt.reply({ embeds: [infoEmbed], components: [lessThan25Row] }); + } + + + + + + + // Send the embed and message component rows + // rows.forEach((row) => { + // msgInt.reply({ embeds: [infoEmbed], components: [row] }); + // }); + + + // if (!checkForRoles(msgInt.guild!, 2)) { + // msgInt.reply("Please run the `/createRoles` command in this server to create the necessary roles for this poll!"); + // } else { + // rows.forEach((row) => { + // msgInt.reply({ embeds: [infoEmbed], components: [row] }); + // }); + // } + + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( + msgInt.guild?.name + )}` + ) + ); + }, +} as ICommand; diff --git a/csClasses.ts b/csClasses.ts new file mode 100644 index 0000000..f2805e2 --- /dev/null +++ b/csClasses.ts @@ -0,0 +1,192 @@ +const csClassOptions = [ + { + label: "COMPSCI 150", + description: "Survey of Computer Science" + }, + { + label: "COMPSCI 202", + description: "Introductory Programming Using Python" + }, + { + label: "COMPSCI 250", + description: "Introductory Computer Programming" + }, + { + label: "COMPSCI 251", + description: "Intermediate Computer Programming" + }, + { + label: "COMPSCI 317", + description: "Discrete Information Structures" + }, + { + label: "COMPSCI 337", + description: "System Programming" + }, + { + label: "COMPSCI 351", + description: "Data Structures and Algorithms" + }, + { + label: "COMPSCI 361", + description: "Introduction to Software Engineering" + }, + { + label: "COMPSCI 423", + description: "Introduction to Natural Language Processing" + }, + { + label: "COMPSCI 431", + description: "Programming Languages Concepts" + }, + { + label: "COMPSCI 431G", + description: "Programming Languages Concepts" + }, + { + label: "COMPSCI 458", + description: "Computer Architecture" + }, + { + label: "COMPSCI 458G", + description: "Computer Architecture" + }, + { + label: "COMPSCI 481", + description: "Server-side Internet Programming" + }, + { + label: "COMPSCI 481G", + description: "Server-side Internet Programming" + }, + { + label: "COMPSCI 520", + description: "Computer Networks" + }, + { + label: "COMPSCI 520G", + description: "Computer Networks" + }, + { + label: "COMPSCI 535", + description: "Algorithm Design and Analysis" + }, + { + label: "COMPSCI 535G", + description: "Algorithm Design and Analysis" + }, + { + label: "COMPSCI 537", + description: "Introduction to Operating Systems" + }, + { + label: "COMPSCI 537G", + description: "Introduction to Operating Systems" + }, + { + label: "COMPSCI 552", + description: "Advanced Object-Oriented Programming" + }, + { + label: "COMPSCI 552G", + description: "Advanced Object-Oriented Programming" + }, + { + label: "COMPSCI 594", + description: "Capstone Project Preparation" + }, + { + label: "COMPSCI 595", + description: "Capstone Project" + }, + { + label: "COMPSCI 599", + description: "Senior Thesis" + }, + { + label: "COMPSCI 657", + description: "Topics in Computer Science: 3D Graphics" + }, + { + label: "COMPSCI 657", + description: "Topics in Computer Science: Cloud Computing" + }, + // { + // label: "COMPSCI 657", + // description: "Topics in Computer Science: Concurrent Programming" + // }, + // { + // label: "COMPSCI 657", + // description: "Topics in Computer Science: Database Security" + // }, + // { + // label: "COMPSCI 657", + // description: "Topics in Computer Science: Introduction to Research Computing" + // }, + // { + // label: "COMPSCI 657", + // description: "Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo" + // }, + // { + // label: "COMPSCI 699", + // description: "Independent Study" + // }, + // { + // label: "COMPSCI 720", + // description: "Computational Models of Decision Making" + // }, + // { + // label: "COMPSCI 723", + // description: "Natural Language Processing" + // }, + // { + // label: "COMPSCI 790", + // description: "Advanced Topics in Computer Science: 3D Graphics" + // }, + // { + // label: "COMPSCI 790", + // description: "Advanced Topics in Computer Science: Cloud Computing" + // }, + // { + // label: "COMPSCI 790", + // description: "Advanced Topics in Computer Science: Concurrent Programming" + // }, + // { + // label: "COMPSCI 790", + // description: "Advanced Topics in Computer Science: Database Security" + // }, + // { + // label: "COMPSCI 790", + // description: "Advanced Topics in Computer Science: Introduction to Research Computing" + // }, + // { + // label: "COMPSCI 790", + // description: "Advanced Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo" + // }, + // { + // label: "COMPSCI 870", + // description: "Medical Informatics Seminar" + // }, + // { + // label: "COMPSCI 888", + // description: "Candidate for Degree" + // }, + // { + // label: "COMPSCI 990", + // description: "Masters Thesis" + // }, + // { + // label: "COMPSCI 995", + // description: "Master's Capstone Project" + // }, + // { + // label: "COMPSCI 998", + // description: "Doctoral Thesis" + // }, + // { + // label: "COMPSCI 999", + // description: "Advanced Independent Study" + // } +] + +export default csClassOptions \ No newline at end of file diff --git a/index.ts b/index.ts index 5f33754..f9a06bd 100644 --- a/index.ts +++ b/index.ts @@ -48,7 +48,7 @@ client.on("ready", () => { typeScript: true, mongoUri: String(process.env.MONGODB_URI), disabledDefaultCommands: ["help", "language"], - botOwners: ["603629606154666024", "680813135556378634"], + botOwners: ["603629606154666024", "680813135556378634", "451761128704573440"], }).setDefaultPrefix(String(process.env.BOT_DEFAULT_PREFIX)); // Set up the connection to the database diff --git a/tsconfig.json b/tsconfig.json index 8fa4c31..6fc73cc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,7 +33,7 @@ // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ // "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "resolveJsonModule": true, /* Enable importing .json files */ + "resolveJsonModule": true, /* Enable importing .json files */ // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ /* JavaScript Support */ From da22400e7c2ecda1be723fd81347e73469bba3dd Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Fri, 26 Aug 2022 21:29:06 -0500 Subject: [PATCH 06/33] Fix Typo --- commands/user/help.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/user/help.ts b/commands/user/help.ts index 6927aed..a4194e6 100644 --- a/commands/user/help.ts +++ b/commands/user/help.ts @@ -17,7 +17,7 @@ import { const color = "#0099ff" ; const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; - const title = "Github"; + const title = "Help and Commands List"; const description = "Welcome to CSSC-Bot! My purpose in this server is to make sure you have the correct roles for this server. My purpose mey evolve over time. You can always use this command to see my latest features."; const fields = [ { From 01445c8d6149bc833af44cca000ec3597fd7a93b Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Fri, 26 Aug 2022 23:41:37 -0500 Subject: [PATCH 07/33] Add basic CI/CD and security analysis --- .github/workflows/codeql.yml | 72 +++++++++++++++++++++++++ .github/workflows/dependency-review.yml | 20 +++++++ .github/workflows/docker-image.yml | 18 +++++++ 3 files changed, 110 insertions(+) create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..27d259f --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,72 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '19 8 * * 2' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..fe461b4 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v3 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v2 diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..04cd263 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,18 @@ +name: Docker Image CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) \ No newline at end of file From 1e45db81369d3f66c92cbb5af94c5c31b3ac016e Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Fri, 26 Aug 2022 23:52:40 -0500 Subject: [PATCH 08/33] Add suuid dependency for short uuid's Also update dependencies --- package-lock.json | 216 +++++++++++++++++++++++++++++++--------------- package.json | 5 +- 2 files changed, 148 insertions(+), 73 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7a81207..a70909a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cssc-bot", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cssc-bot", - "version": "2.0.0", + "version": "2.1.0", "license": "ISC", "dependencies": { "axios": "^0.27.2", @@ -14,6 +14,7 @@ "discord.js": "^13.9.2", "mongoose": "^6.2.2", "path": "^0.12.7", + "short-uuid": "^4.2.0", "ts-node": "^10.5.0", "typescript": "^4.5.5", "wokcommands": "^1.5.3" @@ -22,20 +23,12 @@ "node": "17.x" } }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "engines": { - "node": ">= 12" - } - }, "node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { "node": ">=12" @@ -71,10 +64,32 @@ "node": ">=16.9.0" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@sapphire/async-queue": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.2.tgz", - "integrity": "sha512-rUpMLATsoAMnlN3gecAcr9Ecnw1vG7zi5Xr+IX22YzRzi1k9PF9vKzoT8RuEJbiIszjcimu3rveqUnvwDopz8g==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", + "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" @@ -114,9 +129,9 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" }, "node_modules/@types/node": { - "version": "18.6.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.3.tgz", - "integrity": "sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg==" + "version": "18.7.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz", + "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==" }, "node_modules/@types/node-fetch": { "version": "2.6.2", @@ -195,6 +210,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -234,9 +254,9 @@ ] }, "node_modules/bson": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.5.tgz", - "integrity": "sha512-uqrgcjyOaZsHfz7ea8zLRCLe1u+QGUSzMZmvXqO24CDW7DWoW1qiN9folSwa7hSneTSgM2ykDIzF5kcQQ8cwNw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", + "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", "dependencies": { "buffer": "^5.6.0" }, @@ -365,13 +385,13 @@ "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg==" }, "node_modules/discord.js": { - "version": "13.9.2", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.9.2.tgz", - "integrity": "sha512-wShFlyAyxgQcWzINeufUoT1U0fmju+pPCRzPfJB7CaA0V1tQHc4e0PpO4NQif8sLfZvrQmEILBaIJ0G5I32OxQ==", + "version": "13.10.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.10.3.tgz", + "integrity": "sha512-cIARuxfpQDeqA9Zw3fz4IL20xAhtMsjwJIf7/K82R3n2xROG9/fAx+7qjX8ysp9BfflYqMu2ZskyWq1EAmL5BA==", "dependencies": { "@discordjs/builders": "^0.16.0", "@discordjs/collection": "^0.7.0", - "@sapphire/async-queue": "^1.3.2", + "@sapphire/async-queue": "^1.5.0", "@types/node-fetch": "^2.6.2", "@types/ws": "^8.5.3", "discord-api-types": "^0.33.3", @@ -533,9 +553,9 @@ } }, "node_modules/mongoose": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.5.1.tgz", - "integrity": "sha512-8C0213y279nrSp6Au+WB+l/VczcotMU65jalTJJxU6KYf/Kd8gNW9+B3giWNJOVd8VvKvUQG0suWv/Vngp/83A==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.5.3.tgz", + "integrity": "sha512-0L2ZOPzNQ7kcIgpdfpmVXc+/SypdhzcTlaHXYa983u1lrVp7/i3ekwHpPiTXxYBvV6FwBAsFoHI7+Ovf8tp3Mg==", "dependencies": { "bson": "^4.6.5", "kareem": "2.4.1", @@ -652,6 +672,18 @@ "node": ">=6" } }, + "node_modules/short-uuid": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/short-uuid/-/short-uuid-4.2.0.tgz", + "integrity": "sha512-r3cxuPPZSuF0QkKsK9bBR7u+7cwuCRzWzgjPh07F5N2iIUNgblnMHepBY16xgj5t1lG9iOP9k/TEafY1qhRzaw==", + "dependencies": { + "any-base": "^1.1.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/sift": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", @@ -716,11 +748,11 @@ "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" }, "node_modules/ts-node": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.5.0.tgz", - "integrity": "sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -731,12 +763,13 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" @@ -762,9 +795,9 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -781,6 +814,14 @@ "inherits": "2.0.3" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -846,17 +887,12 @@ } }, "dependencies": { - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" - }, "@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "requires": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" } }, "@discordjs/builders": { @@ -883,10 +919,29 @@ "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz", "integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==" }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@sapphire/async-queue": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.2.tgz", - "integrity": "sha512-rUpMLATsoAMnlN3gecAcr9Ecnw1vG7zi5Xr+IX22YzRzi1k9PF9vKzoT8RuEJbiIszjcimu3rveqUnvwDopz8g==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", + "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" }, "@sapphire/shapeshift": { "version": "3.5.1", @@ -918,9 +973,9 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" }, "@types/node": { - "version": "18.6.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.3.tgz", - "integrity": "sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg==" + "version": "18.7.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz", + "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==" }, "@types/node-fetch": { "version": "2.6.2", @@ -983,6 +1038,11 @@ "color-convert": "^2.0.1" } }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -1008,9 +1068,9 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bson": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.5.tgz", - "integrity": "sha512-uqrgcjyOaZsHfz7ea8zLRCLe1u+QGUSzMZmvXqO24CDW7DWoW1qiN9folSwa7hSneTSgM2ykDIzF5kcQQ8cwNw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", + "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", "requires": { "buffer": "^5.6.0" } @@ -1095,13 +1155,13 @@ "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg==" }, "discord.js": { - "version": "13.9.2", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.9.2.tgz", - "integrity": "sha512-wShFlyAyxgQcWzINeufUoT1U0fmju+pPCRzPfJB7CaA0V1tQHc4e0PpO4NQif8sLfZvrQmEILBaIJ0G5I32OxQ==", + "version": "13.10.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.10.3.tgz", + "integrity": "sha512-cIARuxfpQDeqA9Zw3fz4IL20xAhtMsjwJIf7/K82R3n2xROG9/fAx+7qjX8ysp9BfflYqMu2ZskyWq1EAmL5BA==", "requires": { "@discordjs/builders": "^0.16.0", "@discordjs/collection": "^0.7.0", - "@sapphire/async-queue": "^1.3.2", + "@sapphire/async-queue": "^1.5.0", "@types/node-fetch": "^2.6.2", "@types/ws": "^8.5.3", "discord-api-types": "^0.33.3", @@ -1211,9 +1271,9 @@ } }, "mongoose": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.5.1.tgz", - "integrity": "sha512-8C0213y279nrSp6Au+WB+l/VczcotMU65jalTJJxU6KYf/Kd8gNW9+B3giWNJOVd8VvKvUQG0suWv/Vngp/83A==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.5.3.tgz", + "integrity": "sha512-0L2ZOPzNQ7kcIgpdfpmVXc+/SypdhzcTlaHXYa983u1lrVp7/i3ekwHpPiTXxYBvV6FwBAsFoHI7+Ovf8tp3Mg==", "requires": { "bson": "^4.6.5", "kareem": "2.4.1", @@ -1299,6 +1359,15 @@ "sparse-bitfield": "^3.0.3" } }, + "short-uuid": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/short-uuid/-/short-uuid-4.2.0.tgz", + "integrity": "sha512-r3cxuPPZSuF0QkKsK9bBR7u+7cwuCRzWzgjPh07F5N2iIUNgblnMHepBY16xgj5t1lG9iOP9k/TEafY1qhRzaw==", + "requires": { + "any-base": "^1.1.0", + "uuid": "^8.3.2" + } + }, "sift": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", @@ -1349,11 +1418,11 @@ "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" }, "ts-node": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.5.0.tgz", - "integrity": "sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "requires": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -1364,7 +1433,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" } }, @@ -1374,9 +1443,9 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==" + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" }, "util": { "version": "0.10.4", @@ -1386,6 +1455,11 @@ "inherits": "2.0.3" } }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index dd50d0f..f96f811 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "description": "", "main": "index.ts", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "run": "ts-node index.ts" }, "repository": { "type": "git", @@ -25,8 +25,9 @@ "discord.js": "^13.9.2", "mongoose": "^6.2.2", "path": "^0.12.7", + "short-uuid": "^4.2.0", "ts-node": "^10.5.0", "typescript": "^4.5.5", "wokcommands": "^1.5.3" } -} +} \ No newline at end of file From 555ce6d1f57efaa988944043699424c7846b0ed0 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Fri, 26 Aug 2022 23:54:23 -0500 Subject: [PATCH 09/33] Implement creating course select menus (needs polish) Also add new class json --- commands/owner/csClassPoll.ts | 218 ++++++++++++++------------- csClasses.ts | 192 ------------------------ data/COMPSCI-Fall-Class-List.json | 237 ++++++++++++++++++++++++++++++ 3 files changed, 353 insertions(+), 294 deletions(-) delete mode 100644 csClasses.ts create mode 100644 data/COMPSCI-Fall-Class-List.json diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 9ee898a..88e37b5 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -1,108 +1,122 @@ import chalk from "chalk"; -import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageActionRowComponent } from "discord.js"; +import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; import { ICommand } from "wokcommands"; import { checkForRoles } from "../../rolesOps"; -import csClassOptions from "../../csClasses"; +import classes from "../../data/COMPSCI-Fall-Class-List.json" +import { generate } from 'short-uuid'; +export interface Class { + code: string, + title: string, + info: string +} export default { - name: "csClassPoll", - category: "owner", - description: "Posts the Cs Class Poll", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, - - callback: async ({ client, interaction: msgInt }) => { - // Define embeds used in this command - const infoEmbed = new MessageEmbed() - .setTitle("Choose a role") - .setColor("#0099ff") - .setDescription("Select the option(s) with your current COMPSCI classes.") - .setFooter({ - text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - }); - - - // Create some vars - let csClassOptionsChunks = []; - let lessThan25Row = new MessageActionRow() - let greaterThan25RowList: MessageActionRowComponent[] = []; - - // Check if csClassOptions is larger than 25 items - if (csClassOptions.length > 25) { - // Split csClassOptions into chunks of 25 - for (let i = 0; i < csClassOptions.length; i += 25) { - csClassOptionsChunks.push(csClassOptions.slice(i, i + 25)); - console.log(csClassOptions.slice(i, i + 25)) //! DEBUG - console.log("got here") //! DEBUG - } - } - // Loop through csClassOptionsChunks - for (let i = 0; i < csClassOptionsChunks.length; i++) { - // Loop through csClassOptionsChunks[i] - let menu = new MessageSelectMenu() - menu.setCustomId(`csClassPoll+${i}`) - console.log(`csClassPoll+${i}`) //! DEBUG - menu.setPlaceholder("Select an option") - lessThan25Row.addComponents(menu); - for (let j = 0; j < csClassOptionsChunks[i].length; j++) { - // Create row one of the buttons for the poll - menu.addOptions( - { - label: csClassOptionsChunks[i][j].label, - value: csClassOptionsChunks[i][j].label, - description: csClassOptionsChunks[i][j].description, - } - ) - } - greaterThan25RowList.push(menu); - } - - - // Check if greaterThan25RowList contains any items, and if it does, loop through greaterThan25RowList - if (greaterThan25RowList.length > 0) { - - // console.log(greaterThan25RowList) //! DEBUG - - for (let i = 0; i < greaterThan25RowList.length; i++) { - // Loop through greaterThan25RowList[i] - let row = new MessageActionRow() - row.addComponents(greaterThan25RowList[i]) - msgInt.channel!.send({ embeds: [infoEmbed], components: [row] }); - } - } else { - msgInt.reply({ embeds: [infoEmbed], components: [lessThan25Row] }); - } - - - - - - - // Send the embed and message component rows - // rows.forEach((row) => { - // msgInt.reply({ embeds: [infoEmbed], components: [row] }); - // }); - - - // if (!checkForRoles(msgInt.guild!, 2)) { - // msgInt.reply("Please run the `/createRoles` command in this server to create the necessary roles for this poll!"); - // } else { - // rows.forEach((row) => { - // msgInt.reply({ embeds: [infoEmbed], components: [row] }); - // }); - // } - - // Log the command usage - console.log( - chalk.blue( - `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( - msgInt.guild?.name - )}` - ) - ); - }, + name: "csClassPoll", + category: "owner", + description: "Posts the Cs Class Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, + + callback: async ({ client, interaction: msgInt }) => { + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( + msgInt.guild?.name + ) + }` + ) + ); + + // Crashes the call + // if (!checkForRoles(msgInt.guild!, 2)) { + // msgInt.reply("Please run the `/ createRoles` command in this server to create the necessary roles for this poll!"); + // return + // } + + console.log(`Number of classes ${classes.length}`) + + // split classes into chunks of 25 + let class_chunks: Class[][] = split_list(classes, 25) + + //TODO: remove logging + console.log(`Number of chunks: ${class_chunks.length}`) + //TODO: remove logging + class_chunks.forEach( + (class_chunk, index) => { + console.log(`Chunk#: ${index},\nChunk length: ${class_chunk.length}`) + } + ) + + // Create menus from chunks + let menus: MessageSelectMenu[] = [] + class_chunks.forEach( + (class_chunk, index) => { + let menu = new MessageSelectMenu() + menu.setCustomId(`csClassPoll+${index}`) + menu.setPlaceholder("Select an option") + // create a new list of options from the classes and add to menu + menu.addOptions(class_chunk.map(create_option_from_class)) + menus.push(menu) + } + ) + + menus.forEach( + (menu_chunk, index) => { + let row = new MessageActionRow() + row.addComponents(menu_chunk) + + console.log(`Row: ${row.components}`) + console.log(`Index: ${index}`) + + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the option(s) with your current COMPSCI classes.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); + + if (index == 0) { + msgInt.reply({ embeds: [infoEmbed], components: [row] }); + } + else { + msgInt.channel!.send({ components: [row] }); + } + } + ) + + }, } as ICommand; + +function split_list(list: Array, max_list_len: number) { + // Should split any size list into lists of at most `max_list_len` + let class_chunks = [] + for (let i = 0; i < list.length; i += max_list_len) { + class_chunks.push(list.slice(i, i + max_list_len)) + + } + return class_chunks +} + +function create_option_from_class(_class: Class): MessageSelectOptionData { + if (_class.code.length > 100) { + console.log("\n") + console.log("TOO_LONG: class code") + console.log(_class) + console.log("\n") + + } + + return { + label: _class.code, + value: generate(), + description: _class.title, + } +} + diff --git a/csClasses.ts b/csClasses.ts deleted file mode 100644 index f2805e2..0000000 --- a/csClasses.ts +++ /dev/null @@ -1,192 +0,0 @@ -const csClassOptions = [ - { - label: "COMPSCI 150", - description: "Survey of Computer Science" - }, - { - label: "COMPSCI 202", - description: "Introductory Programming Using Python" - }, - { - label: "COMPSCI 250", - description: "Introductory Computer Programming" - }, - { - label: "COMPSCI 251", - description: "Intermediate Computer Programming" - }, - { - label: "COMPSCI 317", - description: "Discrete Information Structures" - }, - { - label: "COMPSCI 337", - description: "System Programming" - }, - { - label: "COMPSCI 351", - description: "Data Structures and Algorithms" - }, - { - label: "COMPSCI 361", - description: "Introduction to Software Engineering" - }, - { - label: "COMPSCI 423", - description: "Introduction to Natural Language Processing" - }, - { - label: "COMPSCI 431", - description: "Programming Languages Concepts" - }, - { - label: "COMPSCI 431G", - description: "Programming Languages Concepts" - }, - { - label: "COMPSCI 458", - description: "Computer Architecture" - }, - { - label: "COMPSCI 458G", - description: "Computer Architecture" - }, - { - label: "COMPSCI 481", - description: "Server-side Internet Programming" - }, - { - label: "COMPSCI 481G", - description: "Server-side Internet Programming" - }, - { - label: "COMPSCI 520", - description: "Computer Networks" - }, - { - label: "COMPSCI 520G", - description: "Computer Networks" - }, - { - label: "COMPSCI 535", - description: "Algorithm Design and Analysis" - }, - { - label: "COMPSCI 535G", - description: "Algorithm Design and Analysis" - }, - { - label: "COMPSCI 537", - description: "Introduction to Operating Systems" - }, - { - label: "COMPSCI 537G", - description: "Introduction to Operating Systems" - }, - { - label: "COMPSCI 552", - description: "Advanced Object-Oriented Programming" - }, - { - label: "COMPSCI 552G", - description: "Advanced Object-Oriented Programming" - }, - { - label: "COMPSCI 594", - description: "Capstone Project Preparation" - }, - { - label: "COMPSCI 595", - description: "Capstone Project" - }, - { - label: "COMPSCI 599", - description: "Senior Thesis" - }, - { - label: "COMPSCI 657", - description: "Topics in Computer Science: 3D Graphics" - }, - { - label: "COMPSCI 657", - description: "Topics in Computer Science: Cloud Computing" - }, - // { - // label: "COMPSCI 657", - // description: "Topics in Computer Science: Concurrent Programming" - // }, - // { - // label: "COMPSCI 657", - // description: "Topics in Computer Science: Database Security" - // }, - // { - // label: "COMPSCI 657", - // description: "Topics in Computer Science: Introduction to Research Computing" - // }, - // { - // label: "COMPSCI 657", - // description: "Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo" - // }, - // { - // label: "COMPSCI 699", - // description: "Independent Study" - // }, - // { - // label: "COMPSCI 720", - // description: "Computational Models of Decision Making" - // }, - // { - // label: "COMPSCI 723", - // description: "Natural Language Processing" - // }, - // { - // label: "COMPSCI 790", - // description: "Advanced Topics in Computer Science: 3D Graphics" - // }, - // { - // label: "COMPSCI 790", - // description: "Advanced Topics in Computer Science: Cloud Computing" - // }, - // { - // label: "COMPSCI 790", - // description: "Advanced Topics in Computer Science: Concurrent Programming" - // }, - // { - // label: "COMPSCI 790", - // description: "Advanced Topics in Computer Science: Database Security" - // }, - // { - // label: "COMPSCI 790", - // description: "Advanced Topics in Computer Science: Introduction to Research Computing" - // }, - // { - // label: "COMPSCI 790", - // description: "Advanced Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo" - // }, - // { - // label: "COMPSCI 870", - // description: "Medical Informatics Seminar" - // }, - // { - // label: "COMPSCI 888", - // description: "Candidate for Degree" - // }, - // { - // label: "COMPSCI 990", - // description: "Masters Thesis" - // }, - // { - // label: "COMPSCI 995", - // description: "Master's Capstone Project" - // }, - // { - // label: "COMPSCI 998", - // description: "Doctoral Thesis" - // }, - // { - // label: "COMPSCI 999", - // description: "Advanced Independent Study" - // } -] - -export default csClassOptions \ No newline at end of file diff --git a/data/COMPSCI-Fall-Class-List.json b/data/COMPSCI-Fall-Class-List.json new file mode 100644 index 0000000..5ef738b --- /dev/null +++ b/data/COMPSCI-Fall-Class-List.json @@ -0,0 +1,237 @@ +[ + { + "code": "COMPSCI 150", + "title": "Survey of Computer Science", + "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." + }, + { + "code": "COMPSCI 202", + "title": "Introductory Programming Using Python", + "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." + }, + { + "code": "COMPSCI 250", + "title": "Introductory Computer Programming", + "info": "Programming in Python. Basic control structures including recursion. Basic and library data types. Problem solving with objects. Writing classes. Basic software development skills.\n\nCounts as repeat of CompSci 290 with similar topic. Pre-req: Level 30 on Math Placement Test, or a grade of C or better in Math 105 or 108." + }, + { + "code": "COMPSCI 251", + "title": "Intermediate Computer Programming", + "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." + }, + { + "code": "COMPSCI 317", + "title": "Discrete Information Structures", + "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." + }, + { + "code": "COMPSCI 337", + "title": "System Programming", + "info": "Introduction to the application programmer interface for a modern operating system. Overview of mechanisms for object oriented programming and memory management\n\nPrereq: C or better in CompSci 251(P)" + }, + { + "code": "COMPSCI 351", + "title": "Data Structures and Algorithms", + "info": "Programming in a structured, high-level, object-oriented language. Implementation of data structures and algorithms and their application.\n\nPrereq: Math Placement Level 40 or Math 116(P) or 211(P); C or better in CompSci 251(P)." + }, + { + "code": "COMPSCI 361", + "title": "Introduction to Software Engineering", + "info": "Introduction to core topics of software engineering including requirements analysis, object-oriented design, testing, and project management. Overview of ethical and social issues in computing.\n\nPrereq: C or better in CompSci 351(P), satisfaction of GER English Composition competency req." + }, + { + "code": "COMPSCI 423", + "title": "Introduction to Natural Language Processing", + "info": "Introduction to natural language processing programs and an overview of the field. Topics include syntactic frameworks, parsing, semantics, interpretation, and applications.\n\nPrereq: jr st; C or better in CompSci 351(P)." + }, + { + "code": "COMPSCI 431", + "title": "Programming Languages Concepts", + "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." + }, + { + "code": "COMPSCI 431G", + "title": "Programming Languages Concepts", + "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." + }, + { + "code": "COMPSCI 458", + "title": "Computer Architecture", + "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." + }, + { + "code": "COMPSCI 458G", + "title": "Computer Architecture", + "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." + }, + { + "code": "COMPSCI 481", + "title": "Server-side Internet Programming", + "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." + }, + { + "code": "COMPSCI 481G", + "title": "Server-side Internet Programming", + "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." + }, + { + "code": "COMPSCI 520", + "title": "Computer Networks", + "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." + }, + { + "code": "COMPSCI 520G", + "title": "Computer Networks", + "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." + }, + { + "code": "COMPSCI 535", + "title": "Algorithm Design and Analysis", + "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." + }, + { + "code": "COMPSCI 535G", + "title": "Algorithm Design and Analysis", + "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." + }, + { + "code": "COMPSCI 537", + "title": "Introduction to Operating Systems", + "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." + }, + { + "code": "COMPSCI 537G", + "title": "Introduction to Operating Systems", + "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." + }, + { + "code": "COMPSCI 552", + "title": "Advanced Object-Oriented Programming", + "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." + }, + { + "code": "COMPSCI 552G", + "title": "Advanced Object-Oriented Programming", + "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." + }, + { + "code": "COMPSCI 594", + "title": "Capstone Project Preparation", + "info": "Student teams will develop requirements and functionality specifications for their capstone projects and conduct the necessary research on the prior art and technologies to be used.\n\nMeant to be taken in the semester immediately prior to the one in which the student will take COMPSCI 595. Prereq: senior standing." + }, + { + "code": "COMPSCI 595", + "title": "Capstone Project", + "info": "Students will integrate their knowledge of the undergraduate computer science curriculum by implementing a significant computer science team project.\n\nPrereq: senior standing, COMPSCI 351(P), COMPSCI 361(P), COMPSCI 594(P) and credit in at least 6 credits of 400 or higher COMPSCI or ELECENG courses." + }, + { + "code": "COMPSCI 599", + "title": "Senior Thesis", + "info": "Independent scholarly research in Computer Science supervised by a faculty member.\n\nPrereq: sr st & cons instr." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: 3D Graphics", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Cloud Computing", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Concurrent Programming", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Database Security", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Introduction to Research Computing", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 657", + "title": "Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", + "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." + }, + { + "code": "COMPSCI 699", + "title": "Independent Study", + "info": "May be retaken to max of 6 cr by undergraduates. Prereq: jr st; cons instr." + }, + { + "code": "COMPSCI 720", + "title": "Computational Models of Decision Making", + "info": "Theoretical foundations and practical problems of formulating and constructing computational models of decision making.\n\nPrereq: basic course in Probability or Statistics." + }, + { + "code": "COMPSCI 723", + "title": "Natural Language Processing", + "info": "Principles and problems of natural language processing with emphasis on recent advances and open problems. Topics: lexicons, parsing, interpretation, discourse structure, generation, and collaborative interfaces.\n\nNot open to students with cr in CompSci 423. Prereq: grad st; CompSci 422(P) or 710(P)." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: 3D Graphics", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Cloud Computing", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Concurrent Programming", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Database Security", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Introduction to Research Computing", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 790", + "title": "Advanced Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", + "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." + }, + { + "code": "COMPSCI 870", + "title": "Medical Informatics Seminar", + "info": "Presentations by medical informatics affiliated faculty and invited speakers. Graduate students may present their work or published research from recent medical informatics journals or conferences.\n\nMeets once every two weeks for 100 minutes. Prereq: grad st." + }, + { + "code": "COMPSCI 888", + "title": "Candidate for Degree", + "info": "Available for graduate students who must meet minimum credit load requirement.\n\nFee for 1 cr assessed; unit does not count towards credit load for Fin Aid. Repeatable. Satisfactory/Unsatisfactory only. Prereq: graduate standing." + }, + { + "code": "COMPSCI 990", + "title": "Masters Thesis", + "info": "Prereq: grad st; cons instr." + }, + { + "code": "COMPSCI 995", + "title": "Master's Capstone Project", + "info": "Independent project supervised by student's adviser\n\nPrereq: grad st; cons instr & grad prog comm." + }, + { + "code": "COMPSCI 998", + "title": "Doctoral Thesis", + "info": "Prereq: grad st; cons instr & grad prog committee." + }, + { + "code": "COMPSCI 999", + "title": "Advanced Independent Study", + "info": "Prereq: grad st; cons instr & grad prog comm." + } +] \ No newline at end of file From 3be62316f297a1b508a9d1cb1dc6bedaa3ee3956 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Sat, 27 Aug 2022 00:04:15 -0500 Subject: [PATCH 10/33] Update logging --- commands/owner/csClassPoll.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 88e37b5..ab4fad0 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -47,7 +47,7 @@ export default { //TODO: remove logging class_chunks.forEach( (class_chunk, index) => { - console.log(`Chunk#: ${index},\nChunk length: ${class_chunk.length}`) + console.log(`Chunk#: ${index + 1},\nChunk length: ${class_chunk.length}`) } ) @@ -69,9 +69,6 @@ export default { let row = new MessageActionRow() row.addComponents(menu_chunk) - console.log(`Row: ${row.components}`) - console.log(`Index: ${index}`) - // Define embeds used in this command const infoEmbed = new MessageEmbed() .setTitle("Choose a role") @@ -94,8 +91,8 @@ export default { }, } as ICommand; +// Splits any size list into lists of at most `max_list_len` function split_list(list: Array, max_list_len: number) { - // Should split any size list into lists of at most `max_list_len` let class_chunks = [] for (let i = 0; i < list.length; i += max_list_len) { class_chunks.push(list.slice(i, i + max_list_len)) @@ -104,6 +101,7 @@ function split_list(list: Array, max_list_len: number) { return class_chunks } +// consumes a Class and returns Message Selec tOption data function create_option_from_class(_class: Class): MessageSelectOptionData { if (_class.code.length > 100) { console.log("\n") @@ -112,7 +110,6 @@ function create_option_from_class(_class: Class): MessageSelectOptionData { console.log("\n") } - return { label: _class.code, value: generate(), From 0119ecb751703171bcf44a8c613d917978057569 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Sat, 27 Aug 2022 00:11:45 -0500 Subject: [PATCH 11/33] Made variables const --- commands/owner/csClassPoll.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index ab4fad0..9eda41f 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -40,22 +40,22 @@ export default { console.log(`Number of classes ${classes.length}`) // split classes into chunks of 25 - let class_chunks: Class[][] = split_list(classes, 25) + const class_chunks: Class[][] = split_list(classes, 25) //TODO: remove logging console.log(`Number of chunks: ${class_chunks.length}`) //TODO: remove logging class_chunks.forEach( (class_chunk, index) => { - console.log(`Chunk#: ${index + 1},\nChunk length: ${class_chunk.length}`) + console.log(`Chunk: ${index + 1},\t length: ${class_chunk.length}`) } ) // Create menus from chunks - let menus: MessageSelectMenu[] = [] + const menus: MessageSelectMenu[] = [] class_chunks.forEach( (class_chunk, index) => { - let menu = new MessageSelectMenu() + const menu = new MessageSelectMenu() menu.setCustomId(`csClassPoll+${index}`) menu.setPlaceholder("Select an option") // create a new list of options from the classes and add to menu @@ -66,7 +66,7 @@ export default { menus.forEach( (menu_chunk, index) => { - let row = new MessageActionRow() + const row = new MessageActionRow() row.addComponents(menu_chunk) // Define embeds used in this command From 430f7084fe9fdedfe18a38b85cfb1a6bcaa8b480 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Sat, 27 Aug 2022 00:19:01 -0500 Subject: [PATCH 12/33] combine loops --- commands/owner/csClassPoll.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 9eda41f..1a8a8a3 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -52,7 +52,6 @@ export default { ) // Create menus from chunks - const menus: MessageSelectMenu[] = [] class_chunks.forEach( (class_chunk, index) => { const menu = new MessageSelectMenu() @@ -60,14 +59,9 @@ export default { menu.setPlaceholder("Select an option") // create a new list of options from the classes and add to menu menu.addOptions(class_chunk.map(create_option_from_class)) - menus.push(menu) - } - ) - menus.forEach( - (menu_chunk, index) => { const row = new MessageActionRow() - row.addComponents(menu_chunk) + row.addComponents(menu) // Define embeds used in this command const infoEmbed = new MessageEmbed() @@ -85,9 +79,12 @@ export default { else { msgInt.channel!.send({ components: [row] }); } + + + + } ) - }, } as ICommand; From 6506ad20a38b5d60de56de103792b2a0c8e030a3 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Sat, 27 Aug 2022 00:19:45 -0500 Subject: [PATCH 13/33] Move constructing the Embed to inside if statement --- commands/owner/csClassPoll.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 1a8a8a3..49902ea 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -63,17 +63,16 @@ export default { const row = new MessageActionRow() row.addComponents(menu) - // Define embeds used in this command - const infoEmbed = new MessageEmbed() - .setTitle("Choose a role") - .setColor("#0099ff") - .setDescription("Select the option(s) with your current COMPSCI classes.") - .setFooter({ - text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - }); - if (index == 0) { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the option(s) with your current COMPSCI classes.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); msgInt.reply({ embeds: [infoEmbed], components: [row] }); } else { From c7ba1d695b691d11882cd7060a458bac0a83d948 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Sat, 27 Aug 2022 00:21:05 -0500 Subject: [PATCH 14/33] Add comment --- commands/owner/csClassPoll.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 49902ea..11664c2 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -60,6 +60,7 @@ export default { // create a new list of options from the classes and add to menu menu.addOptions(class_chunk.map(create_option_from_class)) + // Add single message to action row const row = new MessageActionRow() row.addComponents(menu) @@ -73,15 +74,12 @@ export default { text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", }); + msgInt.reply({ embeds: [infoEmbed], components: [row] }); } else { msgInt.channel!.send({ components: [row] }); } - - - - } ) }, From b04d11f4ef903cd09eccb223739bdb98366ef5dd Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 30 Aug 2022 19:27:57 -0500 Subject: [PATCH 15/33] Added role models --- models/classModel.ts | 15 +++++++++++++++ models/staffModel.ts | 12 ++++++++++++ models/yearModel.ts | 13 +++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 models/classModel.ts create mode 100644 models/staffModel.ts create mode 100644 models/yearModel.ts diff --git a/models/classModel.ts b/models/classModel.ts new file mode 100644 index 0000000..48fb55d --- /dev/null +++ b/models/classModel.ts @@ -0,0 +1,15 @@ +import mongoose, { Schema } from "mongoose"; + +const CLASS = new Schema({ + id: String, + CODE: String, + TITLE: String, + INFO: String, + ROLE_NAME: String, + ROLE_ID: String, + UUID: String +}); + +const name = "class"; + +export = mongoose.models[name] || mongoose.model(name, CLASS, name); \ No newline at end of file diff --git a/models/staffModel.ts b/models/staffModel.ts new file mode 100644 index 0000000..b0b3532 --- /dev/null +++ b/models/staffModel.ts @@ -0,0 +1,12 @@ +import mongoose, { Schema } from "mongoose"; + +const STAFF = new Schema({ + id: String, + NAME: String, + ROLE_NAME: String, + ROLE_ID: String, +}); + +const name = "staff"; + +export = mongoose.models[name] || mongoose.model(name, STAFF, name); \ No newline at end of file diff --git a/models/yearModel.ts b/models/yearModel.ts new file mode 100644 index 0000000..5c7da47 --- /dev/null +++ b/models/yearModel.ts @@ -0,0 +1,13 @@ +import mongoose, { Schema } from "mongoose"; + +const YEAR = new Schema({ + id: String, + NAME: String, + ROLE_NAME: String, + ROLE_ID: String, + +}); + +const name = "year"; + +export = mongoose.models[name] || mongoose.model(name, YEAR, name); \ No newline at end of file From 320f494e697bab782e5938e83e02155f2dab3c84 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 30 Aug 2022 19:29:03 -0500 Subject: [PATCH 16/33] Removed unused imports --- commands/owner/staffPoll.ts | 2 +- commands/owner/yearPoll.ts | 6 +++--- commands/user/clearRoles.ts | 8 ++++---- commands/user/github.ts | 2 +- commands/user/ping.ts | 2 +- commands/user/status.ts | 2 +- commands/user/version.ts | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/commands/owner/staffPoll.ts b/commands/owner/staffPoll.ts index c02457e..f6ca37a 100644 --- a/commands/owner/staffPoll.ts +++ b/commands/owner/staffPoll.ts @@ -59,7 +59,7 @@ export default { ); // Send the embed and message component rows - if (!checkForRoles(msgInt.guild!, 1)) { + if (!checkForRoles(msgInt.guild!)) { msgInt.reply("Please run the `/createRoles` command in this server to create the necessary roles for this poll!"); } else { msgInt.reply({ embeds: [infoEmbed], components: [row] }); diff --git a/commands/owner/yearPoll.ts b/commands/owner/yearPoll.ts index 0b967ca..07b43cc 100644 --- a/commands/owner/yearPoll.ts +++ b/commands/owner/yearPoll.ts @@ -1,5 +1,5 @@ import chalk from "chalk"; -import { MessageEmbed, MessageActionRow, MessageSelectMenu, Message } from "discord.js"; +import { MessageEmbed, MessageActionRow, MessageSelectMenu } from "discord.js"; import { ICommand } from "wokcommands"; import { checkForRoles } from "../../rolesOps"; @@ -68,8 +68,8 @@ export default { ); // Send the embed and message component rows - if (!checkForRoles(msgInt.guild!, 0)) { - msgInt.reply("Please run the /createRoles command in this server to create the necessary roles for this poll!"); + if (!checkForRoles(msgInt.guild!)) { + msgInt.reply({content: "Please run the /createRoles command in this server to create the necessary roles for this poll!", ephemeral: true}); } else { msgInt.reply({ embeds: [infoEmbed], components: [row] }); } diff --git a/commands/user/clearRoles.ts b/commands/user/clearRoles.ts index d3d49a3..6f41e84 100644 --- a/commands/user/clearRoles.ts +++ b/commands/user/clearRoles.ts @@ -1,8 +1,7 @@ import chalk from "chalk"; import { GuildMember } from "discord.js"; import { ICommand } from "wokcommands"; -import { returnRoles as roleDictionary } from "../../definitions"; -import { removePrevRole } from "../../rolesOps"; +import { removeRole } from "../../rolesOps"; export default { name: "clear", @@ -17,8 +16,9 @@ export default { // Remove roles from user if (!interaction.member) return; const member = interaction.member as GuildMember; - removePrevRole(member, 0); - removePrevRole(member, 1); + removeRole(member, "class"); + removeRole(member, "year"); + removeRole(member, "staff"); // Reply to the user interaction.reply({ content: "Cleared all roles that I have assigned to you.", ephemeral: true }); diff --git a/commands/user/github.ts b/commands/user/github.ts index 7041b4a..32641d1 100644 --- a/commands/user/github.ts +++ b/commands/user/github.ts @@ -1,5 +1,5 @@ import chalk from "chalk"; -import { MessageEmbed, TextChannel } from "discord.js"; +import { MessageEmbed } from "discord.js"; import { ICommand } from "wokcommands"; export default { diff --git a/commands/user/ping.ts b/commands/user/ping.ts index 6f58d99..69c2479 100644 --- a/commands/user/ping.ts +++ b/commands/user/ping.ts @@ -1,4 +1,4 @@ -import { MessageEmbed, TextChannel } from "discord.js"; +import { MessageEmbed } from "discord.js"; import { ICommand } from "wokcommands"; import chalk from "chalk"; diff --git a/commands/user/status.ts b/commands/user/status.ts index 4150706..53d1fef 100644 --- a/commands/user/status.ts +++ b/commands/user/status.ts @@ -1,5 +1,5 @@ import chalk from "chalk"; -import { MessageEmbed, TextChannel } from "discord.js"; +import { MessageEmbed } from "discord.js"; import { ICommand } from "wokcommands"; export default { diff --git a/commands/user/version.ts b/commands/user/version.ts index b9dcc88..f6f833b 100644 --- a/commands/user/version.ts +++ b/commands/user/version.ts @@ -1,4 +1,4 @@ -import { MessageEmbed, TextChannel } from "discord.js"; +import { MessageEmbed } from "discord.js"; import { ICommand } from "wokcommands"; import chalk from "chalk"; From 49c04ca0f2d6dbd102721f342c2854c492c4286a Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 30 Aug 2022 19:30:16 -0500 Subject: [PATCH 17/33] Update bot to store all data in mongodb --- commands/owner/createRoles.ts | 32 ++-- commands/owner/csClassPoll.ts | 195 ++++++++++++------------ commands/owner/csClassTest.ts | 88 +++++++++++ data/COMPSCI-Fall-Class-List.json | 237 ------------------------------ definitions.ts | 45 ------ features/interactionCreate.ts | 83 ++++++----- index.ts | 8 +- rolesOps.ts | 118 +++++++++------ 8 files changed, 332 insertions(+), 474 deletions(-) create mode 100644 commands/owner/csClassTest.ts delete mode 100644 data/COMPSCI-Fall-Class-List.json delete mode 100644 definitions.ts diff --git a/commands/owner/createRoles.ts b/commands/owner/createRoles.ts index 62f1827..4fb1286 100644 --- a/commands/owner/createRoles.ts +++ b/commands/owner/createRoles.ts @@ -10,17 +10,27 @@ export default { testOnly: false, guildOnly: true, requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, + ownerOnly: true, callback: async ({ interaction }) => { - console.log(chalk.green("Creating roles...\nCopy and paste the following output into your .env file")); - console.log(chalk.red("------------------------------------------------------")) - // Create the roles - createRoles(interaction.guild!, 0) - createRoles(interaction.guild!, 1) - interaction.reply("Roles created! Check the console for the role IDs\nPaste the output into your .env file and restart the bot\n "); + console.log(chalk.green("Creating roles...\nCopy and paste the following output into your .env file")); + console.log(chalk.red("------------------------------------------------------")); + // Create the roles + createRoles(interaction.guild!, "class"); + createRoles(interaction.guild!, "staff"); + createRoles(interaction.guild!, "year"); + interaction.reply({ + content: "Roles created! Check the console for the role IDs\nPaste the output into your .env file and restart the bot\n ", + ephemeral: true, + }); - // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/yearPoll`)} command in ${chalk.yellow(interaction.guild?.name)}`)); - }, -} as ICommand; \ No newline at end of file + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/yearPoll`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, +} as ICommand; diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 11664c2..ac03001 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -1,113 +1,112 @@ -import chalk from "chalk"; -import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; -import { ICommand } from "wokcommands"; -import { checkForRoles } from "../../rolesOps"; -import classes from "../../data/COMPSCI-Fall-Class-List.json" -import { generate } from 'short-uuid'; -export interface Class { - code: string, - title: string, - info: string -} +// import chalk from "chalk"; +// import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; +// import { ICommand } from "wokcommands"; +// export interface Class { +// code: string, +// title: string, +// info: string, +// roleId: string, +// } -export default { - name: "csClassPoll", - category: "owner", - description: "Posts the Cs Class Poll", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, +// export default { +// name: "csClassPoll", +// category: "owner", +// description: "Posts the Cs Class Poll", +// slash: true, +// testOnly: false, +// guildOnly: true, +// requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], +// ownerOnly: true, - callback: async ({ client, interaction: msgInt }) => { - // Log the command usage - console.log( - chalk.blue( - `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( - msgInt.guild?.name - ) - }` - ) - ); +// callback: async ({ client, interaction: msgInt }) => { + - // Crashes the call - // if (!checkForRoles(msgInt.guild!, 2)) { - // msgInt.reply("Please run the `/ createRoles` command in this server to create the necessary roles for this poll!"); - // return - // } +// // Crashes the call +// // if (!checkForRoles(msgInt.guild!, 2)) { +// // msgInt.reply("Please run the `/ createRoles` command in this server to create the necessary roles for this poll!"); +// // return +// // } - console.log(`Number of classes ${classes.length}`) +// console.log(`Number of classes ${classes.length}`) - // split classes into chunks of 25 - const class_chunks: Class[][] = split_list(classes, 25) +// // split classes into chunks of 25 +// const class_chunks: Class[][] = split_list(classes, 25) - //TODO: remove logging - console.log(`Number of chunks: ${class_chunks.length}`) - //TODO: remove logging - class_chunks.forEach( - (class_chunk, index) => { - console.log(`Chunk: ${index + 1},\t length: ${class_chunk.length}`) - } - ) +// //TODO: remove logging +// console.log(`Number of chunks: ${class_chunks.length}`) +// //TODO: remove logging +// class_chunks.forEach( +// (class_chunk, index) => { +// console.log(`Chunk: ${index + 1},\t length: ${class_chunk.length}`) +// } +// ) - // Create menus from chunks - class_chunks.forEach( - (class_chunk, index) => { - const menu = new MessageSelectMenu() - menu.setCustomId(`csClassPoll+${index}`) - menu.setPlaceholder("Select an option") - // create a new list of options from the classes and add to menu - menu.addOptions(class_chunk.map(create_option_from_class)) +// // Create menus from chunks +// class_chunks.forEach( +// (class_chunk, index) => { +// const menu = new MessageSelectMenu() +// menu.setCustomId(`csClassPoll+${index}`) +// menu.setPlaceholder("Select an option") +// // create a new list of options from the classes and add to menu +// menu.addOptions(class_chunk.map(create_option_from_class)) - // Add single message to action row - const row = new MessageActionRow() - row.addComponents(menu) +// // Add single message to action row +// const row = new MessageActionRow() +// row.addComponents(menu) - if (index == 0) { - // Define embeds used in this command - const infoEmbed = new MessageEmbed() - .setTitle("Choose a role") - .setColor("#0099ff") - .setDescription("Select the option(s) with your current COMPSCI classes.") - .setFooter({ - text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - }); +// if (index == 0) { +// // Define embeds used in this command +// const infoEmbed = new MessageEmbed() +// .setTitle("Choose a role") +// .setColor("#0099ff") +// .setDescription("Select the option(s) with your current COMPSCI classes.") +// .setFooter({ +// text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, +// iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", +// }); - msgInt.reply({ embeds: [infoEmbed], components: [row] }); - } - else { - msgInt.channel!.send({ components: [row] }); - } - } - ) - }, -} as ICommand; +// msgInt.reply({ embeds: [infoEmbed], components: [row] }); +// } +// else { +// msgInt.channel!.send({ components: [row] }); +// } +// } +// ) +// // Log the command usage +// console.log( +// chalk.blue( +// `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( +// msgInt.guild?.name +// ) +// }` +// ) +// ); +// }, +// } as ICommand; -// Splits any size list into lists of at most `max_list_len` -function split_list(list: Array, max_list_len: number) { - let class_chunks = [] - for (let i = 0; i < list.length; i += max_list_len) { - class_chunks.push(list.slice(i, i + max_list_len)) +// // Splits any size list into lists of at most `max_list_len` +// function split_list(list: Array, max_list_len: number) { +// let class_chunks = [] +// for (let i = 0; i < list.length; i += max_list_len) { +// class_chunks.push(list.slice(i, i + max_list_len)) - } - return class_chunks -} +// } +// return class_chunks +// } -// consumes a Class and returns Message Selec tOption data -function create_option_from_class(_class: Class): MessageSelectOptionData { - if (_class.code.length > 100) { - console.log("\n") - console.log("TOO_LONG: class code") - console.log(_class) - console.log("\n") +// // consumes a Class and returns Message Selec tOption data +// function create_option_from_class(_class: Class): MessageSelectOptionData { +// if (_class.code.length > 100) { +// console.log("\n") +// console.log("TOO_LONG: class code") +// console.log(_class) +// console.log("\n") - } - return { - label: _class.code, - value: generate(), - description: _class.title, - } -} +// } +// return { +// label: _class.code, +// value: _class.roleId, +// description: _class.title, +// } +// } diff --git a/commands/owner/csClassTest.ts b/commands/owner/csClassTest.ts new file mode 100644 index 0000000..459758c --- /dev/null +++ b/commands/owner/csClassTest.ts @@ -0,0 +1,88 @@ +import { MessageEmbed, MessageActionRow, MessageSelectMenu } from "discord.js"; +import chalk from "chalk"; +import { ICommand } from "wokcommands"; +import classModel from "../../models/classModel"; +import { checkForRoles } from "../../rolesOps"; + +export default { + name: "csclasstest", + category: "owner", + description: "Posts the Cs Class Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, + + callback: async ({ client, interaction: msgInt }) => { + if (!checkForRoles(msgInt.guild!)) { + msgInt.reply("Please run the `/ createRoles` command in this server to create the necessary roles for this poll!"); + return + } + + const classes = await classModel.find({}); + + console.log(`Number of classes ${classes.length}`); + + const row = new MessageActionRow(); + const row2 = new MessageActionRow(); + let menu = new MessageSelectMenu(); //! this might need to be a `let` + let menu2 = new MessageSelectMenu(); + row.addComponents(menu); + row2.addComponents(menu2); + menu.setCustomId(`csClassPoll+0`); + menu2.setCustomId(`csClassPoll+1`); + menu.setPlaceholder("Select an option"); + menu2.setPlaceholder("Select an option"); + + while (menu.options.length <= 25) { + console.log(menu.options.length); + const label = classes[menu.options.length].CODE as string; + const value = classes[menu.options.length].UUID as string; + const description = classes[menu.options.length].TITLE as string; + menu.addOptions({ + label: label, + value: value, + description: description, + }); + } + if (menu.options.length >= 25) { + while (menu2.options.length < 25 && classes.length > menu2.options.length) { + console.log(menu2.options.length); + const label = classes[menu2.options.length + 24].CODE as string; + const value = classes[menu2.options.length + 24].UUID as string; + const description = classes[menu2.options.length + 24].TITLE as string; + menu2.addOptions({ + label: label, + value: value, + description: description, + }); + } + } + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the option(s) with your current COMPSCI classes.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); + + if (menu2.options.length > 1) { + msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); + msgInt.channel?.send({ content: "test", components: [row2] }); + } else { + msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); + + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green( + `/csclasspoll` + )} command in ${chalk.yellow(msgInt.guild?.name)}` + ) + ); + } + }, +} as ICommand; diff --git a/data/COMPSCI-Fall-Class-List.json b/data/COMPSCI-Fall-Class-List.json deleted file mode 100644 index 5ef738b..0000000 --- a/data/COMPSCI-Fall-Class-List.json +++ /dev/null @@ -1,237 +0,0 @@ -[ - { - "code": "COMPSCI 150", - "title": "Survey of Computer Science", - "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." - }, - { - "code": "COMPSCI 202", - "title": "Introductory Programming Using Python", - "info": "A survey of computer science. Topics include data storage and manipulation, operating systems and networks, algorithms and data structures, programming languages, artificial intelligence, and computability.\n\nCounts as repeat of CompSci 299 with similar topic. Prereq: none." - }, - { - "code": "COMPSCI 250", - "title": "Introductory Computer Programming", - "info": "Programming in Python. Basic control structures including recursion. Basic and library data types. Problem solving with objects. Writing classes. Basic software development skills.\n\nCounts as repeat of CompSci 290 with similar topic. Pre-req: Level 30 on Math Placement Test, or a grade of C or better in Math 105 or 108." - }, - { - "code": "COMPSCI 251", - "title": "Intermediate Computer Programming", - "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." - }, - { - "code": "COMPSCI 317", - "title": "Discrete Information Structures", - "info": "Problem solving with structured programming techniques using an object-oriented programming language, including control structures, functions, arrays, vectors, and pre-defined objects.\n\nPrereq: Math Placement level 30." - }, - { - "code": "COMPSCI 337", - "title": "System Programming", - "info": "Introduction to the application programmer interface for a modern operating system. Overview of mechanisms for object oriented programming and memory management\n\nPrereq: C or better in CompSci 251(P)" - }, - { - "code": "COMPSCI 351", - "title": "Data Structures and Algorithms", - "info": "Programming in a structured, high-level, object-oriented language. Implementation of data structures and algorithms and their application.\n\nPrereq: Math Placement Level 40 or Math 116(P) or 211(P); C or better in CompSci 251(P)." - }, - { - "code": "COMPSCI 361", - "title": "Introduction to Software Engineering", - "info": "Introduction to core topics of software engineering including requirements analysis, object-oriented design, testing, and project management. Overview of ethical and social issues in computing.\n\nPrereq: C or better in CompSci 351(P), satisfaction of GER English Composition competency req." - }, - { - "code": "COMPSCI 423", - "title": "Introduction to Natural Language Processing", - "info": "Introduction to natural language processing programs and an overview of the field. Topics include syntactic frameworks, parsing, semantics, interpretation, and applications.\n\nPrereq: jr st; C or better in CompSci 351(P)." - }, - { - "code": "COMPSCI 431", - "title": "Programming Languages Concepts", - "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." - }, - { - "code": "COMPSCI 431G", - "title": "Programming Languages Concepts", - "info": "Examination of abstract features of languages. Study of syntactic and semantic models; design and programming in procedural, object-oriented, functional and logical languages. Implementation methods.\n\nPrereq: jr st; grade of C or better in CompSci 351(252)(P)." - }, - { - "code": "COMPSCI 458", - "title": "Computer Architecture", - "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." - }, - { - "code": "COMPSCI 458G", - "title": "Computer Architecture", - "info": "Processor organization, memory hierarchy, pipelining, computer architectures exploiting instruction/data/thread level parallelism, warehouse scale computers.\n\nCOMPSCI 458 and ELECENG 458 are jointly offered and count as repeats of one another. Prereq: sophomore standing and a grade of C or better in COMPSCI 241(P) or COMPSCI 251(P)." - }, - { - "code": "COMPSCI 481", - "title": "Server-side Internet Programming", - "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." - }, - { - "code": "COMPSCI 481G", - "title": "Server-side Internet Programming", - "info": "Introduces students to the concept of server-side programming and web applications development. Topics include dynamic web site development, session management, security, and relational databases.\n\nPrereq:jr st; one of COMPSCI 113 (P), INFOST 320 (P), or ART 324 (P); C or better in COMPSCI 202(P), COMPSCI 361(P) or COMPST 702(P)." - }, - { - "code": "COMPSCI 520", - "title": "Computer Networks", - "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." - }, - { - "code": "COMPSCI 520G", - "title": "Computer Networks", - "info": "Layered network architecture, protocols, data transmission, local area networks, multiplexing and switching, routing flow and congestion control, internetworking, wireless networking, network reliability and security.\n\nPrereq: jr. st; CompSci 315(215)(P) or CompSci 458(P) or ElecEng 367(P)." - }, - { - "code": "COMPSCI 535", - "title": "Algorithm Design and Analysis", - "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." - }, - { - "code": "COMPSCI 535G", - "title": "Algorithm Design and Analysis", - "info": "Introduction to abstract data structures, analysis of time and space requirements of numerical and non-numerical algorithms methods for data manipulation.\n\nPrereq: junior standing; MATH 211(P), MATH 213(P), MATH 221(P) or MATH 231(P); a grade of C or better in COMPSCI 351(P); and either COMPSCI 317(P) or both MATH 341(P) and MTHSTAT 361(P)." - }, - { - "code": "COMPSCI 537", - "title": "Introduction to Operating Systems", - "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." - }, - { - "code": "COMPSCI 537G", - "title": "Introduction to Operating Systems", - "info": "Process management including process creation, switching, multithreading, scheduling, communication and concurrency control; memory management including paging, segmentation and virtual memory; systems programming.\n\nPrereq: jr st; CompSci 458(C) or ElecEng 458(C); CompSci 337(P)." - }, - { - "code": "COMPSCI 552", - "title": "Advanced Object-Oriented Programming", - "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." - }, - { - "code": "COMPSCI 552G", - "title": "Advanced Object-Oriented Programming", - "info": "An advanced course in object-oriented programming. Abstraction; single and multiple inheritance; dynamic binding of functions; polymorphic types and operators; survey of object-oriented techniques.\n\nPrereq: jr st; C or better in both CompSci 351(P) & 361(P)." - }, - { - "code": "COMPSCI 594", - "title": "Capstone Project Preparation", - "info": "Student teams will develop requirements and functionality specifications for their capstone projects and conduct the necessary research on the prior art and technologies to be used.\n\nMeant to be taken in the semester immediately prior to the one in which the student will take COMPSCI 595. Prereq: senior standing." - }, - { - "code": "COMPSCI 595", - "title": "Capstone Project", - "info": "Students will integrate their knowledge of the undergraduate computer science curriculum by implementing a significant computer science team project.\n\nPrereq: senior standing, COMPSCI 351(P), COMPSCI 361(P), COMPSCI 594(P) and credit in at least 6 credits of 400 or higher COMPSCI or ELECENG courses." - }, - { - "code": "COMPSCI 599", - "title": "Senior Thesis", - "info": "Independent scholarly research in Computer Science supervised by a faculty member.\n\nPrereq: sr st & cons instr." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: 3D Graphics", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Cloud Computing", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Concurrent Programming", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Database Security", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Introduction to Research Computing", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 657", - "title": "Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", - "info": "Lectures on recent advances in computer science. Specific credits and any additional prerequisites will be announced in Schedule of Classes whenever course is offered.\n\nMay be retaken w/chg in topic to 9 cr max. Prereq: jr st." - }, - { - "code": "COMPSCI 699", - "title": "Independent Study", - "info": "May be retaken to max of 6 cr by undergraduates. Prereq: jr st; cons instr." - }, - { - "code": "COMPSCI 720", - "title": "Computational Models of Decision Making", - "info": "Theoretical foundations and practical problems of formulating and constructing computational models of decision making.\n\nPrereq: basic course in Probability or Statistics." - }, - { - "code": "COMPSCI 723", - "title": "Natural Language Processing", - "info": "Principles and problems of natural language processing with emphasis on recent advances and open problems. Topics: lexicons, parsing, interpretation, discourse structure, generation, and collaborative interfaces.\n\nNot open to students with cr in CompSci 423. Prereq: grad st; CompSci 422(P) or 710(P)." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: 3D Graphics", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Cloud Computing", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Concurrent Programming", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Database Security", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Introduction to Research Computing", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 790", - "title": "Advanced Topics in Computer Science: Social Computing: Platforms, Technologies, and Peo", - "info": "Discussion of special advanced topics in theoretical as well as applied areas in computer science.\n\nRetakable w/chg in topic to 9 cr max. Specific topics may be jointly-offered w/Philos. Prereq: grad st; add'l prereqs depending on topic." - }, - { - "code": "COMPSCI 870", - "title": "Medical Informatics Seminar", - "info": "Presentations by medical informatics affiliated faculty and invited speakers. Graduate students may present their work or published research from recent medical informatics journals or conferences.\n\nMeets once every two weeks for 100 minutes. Prereq: grad st." - }, - { - "code": "COMPSCI 888", - "title": "Candidate for Degree", - "info": "Available for graduate students who must meet minimum credit load requirement.\n\nFee for 1 cr assessed; unit does not count towards credit load for Fin Aid. Repeatable. Satisfactory/Unsatisfactory only. Prereq: graduate standing." - }, - { - "code": "COMPSCI 990", - "title": "Masters Thesis", - "info": "Prereq: grad st; cons instr." - }, - { - "code": "COMPSCI 995", - "title": "Master's Capstone Project", - "info": "Independent project supervised by student's adviser\n\nPrereq: grad st; cons instr & grad prog comm." - }, - { - "code": "COMPSCI 998", - "title": "Doctoral Thesis", - "info": "Prereq: grad st; cons instr & grad prog committee." - }, - { - "code": "COMPSCI 999", - "title": "Advanced Independent Study", - "info": "Prereq: grad st; cons instr & grad prog comm." - } -] \ No newline at end of file diff --git a/definitions.ts b/definitions.ts deleted file mode 100644 index a9678cc..0000000 --- a/definitions.ts +++ /dev/null @@ -1,45 +0,0 @@ -type dict = { - [key: string]: string; -}; - -function returnRoles(): dict[] { - let studentRoleDictionary = { - Prefrosh: String(process.env.Prefrosh), - Freshman: String(process.env.Freshman), - Sophomore: String(process.env.Sophomore), - Junior: String(process.env.Junior), - Senior: String(process.env.Senior), - Graduatestudent: String(process.env.Graduatestudent), - Alumni: String(process.env.Alumni), - }; - let staffRoleDictionary = { - Tutor: String(process.env.Tutor), - Sileader: String(process.env.Sileader), - Ta: String(process.env.Ta), - Studentemployee: String(process.env.Studentemployee), - Professor: String(process.env.Professor) - } - if (process.env.debugMode === "true") { - - let studentRoleDictionary = { - Prefrosh: "1003849993255403601", - Freshman: "1003367383181824131", - Sophomore: "1003367410679685262", - Junior: "1003367473053171743", - Senior: "1003850030920245409", - Graduatestudent: "1003850131994583122", - Alumni: "1003850162935975960" - }; - let staffRoleDictionary = { - Tutor: "1003850195202744560", - Sileader: "1003850241591742595", - Ta: "1003850228643934260", - Studentemployee: "1003850274840002620", - Professor: "1003881218686865439" - } - return [studentRoleDictionary, staffRoleDictionary]; - }; - return [studentRoleDictionary, staffRoleDictionary]; -} - -export { returnRoles }; diff --git a/features/interactionCreate.ts b/features/interactionCreate.ts index 320bb94..e70dc01 100644 --- a/features/interactionCreate.ts +++ b/features/interactionCreate.ts @@ -1,12 +1,15 @@ import { Client, MessageEmbed, GuildMember } from "discord.js"; -import { removePrevRole, addNewRole } from "../rolesOps"; +import { removeRole, addNewRole } from "../rolesOps"; // Listen interactionCreate events from the client export default (client: Client): void => { client.on("interactionCreate", async (interaction) => { // Make sure the interaction is from a select menu if (!interaction.isSelectMenu()) return; - + const color = "#0099ff"; + const description = `You selected the ${interaction.values[0]} role.`; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; // Constants for all interactions const member = interaction.member as GuildMember; @@ -21,52 +24,64 @@ export default (client: Client): void => { // Create and send the embed object interaction.reply({ - embeds: [ - new MessageEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter({text: footer, iconURL: footerIcon}), - ], - ephemeral: true - }); + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }), + ], + ephemeral: true, + }); // Remove any previous roles in the dictionary from the user - if(interaction.values[0] === "None") { - removePrevRole(member, 0); + if (interaction.values[0] === "None") { + removeRole(member, "year"); return; } - removePrevRole(member, 0); + removeRole(member, "year"); // Assign the new role to the user - addNewRole(member, 0, interaction.values[0]); + addNewRole(member, "year", interaction.values[0]); } else if (interaction.customId === "collegeStaffPoll") { - // Set the embed values + // Set the embed title const title = "College Staff Poll"; - const color = "#0099ff"; - const description = `You selected the ${interaction.values[0]} role.`; - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; - // Create and send the embed object interaction.reply({ - embeds: [ - new MessageEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter({text: footer, iconURL: footerIcon}), - ], - ephemeral: true - }); + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }), + ], + ephemeral: true, + }); // Remove any previous roles in the dictionary from the user - if(interaction.values[0] === "None") { - removePrevRole(member, 1); + if (interaction.values[0] === "None") { + removeRole(member, "staff"); return; } - removePrevRole(member, 1); + removeRole(member, "staff"); // Assign the new role to the user - addNewRole(member, 1, interaction.values[0]); + addNewRole(member, "staff", interaction.values[0]); + } else if (interaction.customId === "csClassPoll+0" || interaction.customId === "csClassPoll+1") { + // Set the embed title + const title = "CS Class Poll"; + // Create and send the embed object + interaction.reply({ + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }), + ], + ephemeral: true, + }); + // Assign the new role to the user + + addNewRole(member, "class", interaction.values[0]); } }); }; diff --git a/index.ts b/index.ts index f9a06bd..05be61e 100644 --- a/index.ts +++ b/index.ts @@ -20,16 +20,10 @@ client.on("ready", () => { if (client.user) { console.log(chalk.green(`Logged in as ${client.user.tag}!`)); console.log(chalk.yellow.bold(`I am running version: ${process.env.VERSION}`)); - if (process.env.debugMode === "true") { - console.log(chalk.red.bold("Debug mode is enabled!\nTesting Server roles are loaded!")); - } else if (process.env.debugMode === "false") { - console.log(chalk.red.bold("Debug mode is disabled!\nProduction Server roles are loaded!")); - } // Check to make sure the roles exist in all servers console.log("Checking if all roles exist in servers.") client.guilds.cache.forEach(async (guild) => { - checkForRoles(guild, 0); - checkForRoles(guild, 1); + checkForRoles(guild); }); } diff --git a/rolesOps.ts b/rolesOps.ts index 5e0bdc9..e51e28d 100644 --- a/rolesOps.ts +++ b/rolesOps.ts @@ -1,80 +1,114 @@ import { GuildMember, Guild } from "discord.js"; -import { returnRoles, returnRoles as roleDictionary } from "./definitions"; import chalk from "chalk"; +import classModel from "./models/classModel"; +import staffModel from "./models/staffModel"; +import yearModel from "./models/yearModel"; + + +async function dbQuery(){ + const classes = await classModel.find({}); + const staff = await staffModel.find({}); + const years = await yearModel.find({}); + return [classes, staff, years]; +} export async function getUsersRoles(member: GuildMember): Promise { let list = ""; - for (const role of Object.values(roleDictionary()[0])) { - if (member.roles.cache.has(role)) { - list += `${member.guild.roles.cache.get(role)?.name}\n`; - } - } - for (const role of Object.values(roleDictionary()[1])) { - if (member.roles.cache.has(role)) { - list += `${member.guild.roles.cache.get(role)?.name}\n`; + for (const group of await dbQuery()) { + for (const element of group) { + if (member.roles.cache.has(element.ROLE_ID)) { + list += `${member.guild.roles.cache.get(element.ROLE_NAME)?.name}\n`; + } } } return list; } -export async function removePrevRole(member: GuildMember, listID: number): Promise { +export async function removeRole(member: GuildMember, type: string): Promise { // This function is triggered when a user changes their role, // it removes the previous role from the user - for (const role of Object.values(roleDictionary()[listID])) { - if (member.roles.cache.has(role)) { - await member.roles.remove(role); - console.log(chalk.green(`Removed role ${chalk.green(role)} from ${chalk.yellow(member.user.tag)}`)); + let list = []; + if (type === "class") { + list = await classModel.find({}); + } else if (type === "staff") { + list = await staffModel.find({}); + } else if (type === "year") { + list = await yearModel.find({}); + } + + for (const role of list) { + if (member.roles.cache.has(role.ROLE_ID)) { + await member.roles.remove(role.ROLE_ID); + console.log(chalk.green(`Removed role ${chalk.green(role.ROLE_ID)} from ${chalk.yellow(member.user.tag)}`)); } } } -export async function addNewRole(member: GuildMember, listID: number, roleKey: string) { - // This function is triggered when a user changes their role, - // it adds the new role to the user - const role = roleDictionary()[listID][roleKey] - await member.roles.add(role); - console.log(chalk.green(`Added role ${chalk.green(role)} to ${chalk.yellow(member.user.tag)}`)); +export async function addNewRole(member: GuildMember, type: string, uuid: string) { + // This function is triggered when a user changes their role, it adds the new role to the user + let role; + if (type === "class") { + role = await classModel.findOne({ UUID: uuid }); + } else if (type === "staff") { + role = await staffModel.findOne({ UUID: uuid }); + } else if (type === "year") { + role = await yearModel.findOne({ UUID: uuid }); + } + if (member.roles.cache.has(role?.ROLE_ID)) { + await member.roles.add(role?.ROLE_ID); + console.log(chalk.green(`Added role ${chalk.green(role.ROLE_NAME)} to ${chalk.yellow(member.user.tag)}`)); + } } -export async function createRoles(guild: Guild, listID: number): Promise { - // Get the key names of the roles object and check if a role with that name exists in the guild. - // If not create those roles and print their id's to the console. - Object.keys(roleDictionary()[listID]).forEach(async (roleName) => { - // If the guild does not have the role, create it - if (!guild.roles.cache.find((r) => r.name === roleName)) { +export async function createRoles(guild: Guild, type: string): Promise { + let list; + if (type === "class") { + list = await classModel.find({}); + } else if (type === "staff") { + list = await staffModel.find({}); + } else if (type === "year") { + list = await yearModel.find({}); + } + + list?.forEach(async (element) => { + if (!guild.roles.cache.find((r) => r.name === element.ROLE_NAME)) { // Create the role - const role = await guild.roles.create({ name: roleName }); + const role = await guild.roles.create({ name: element.ROLE_NAME }); + element.ROLE_ID = role.id; + element.save(); // Print the role id to the console - console.log(chalk.yellow(`${roleName}=${role.id}`)); + console.log(chalk.yellow(`${element}: ${role?.id}`)); } else { // If the role already exists, print the id to the console - const roleId = guild.roles.cache.find((r) => r.name === roleName)?.id; - console.log(chalk.yellow(`${roleName}=${roleId}`)); + const role = guild.roles.cache.find((r) => r.name === element.ROLE_NAME); + element.ROLE_ID = role?.id; + element.save(); + console.log(chalk.yellow(`${element}: ${role?.id}`)); } }); } -export function checkForRoles(guild: Guild, listID: number): boolean { +export async function checkForRoles(guild: Guild): Promise { // Check if all roles exist in a guild // Return true if they do, false if they don't - const roles = returnRoles()[listID]; - const roleNames = Object.keys(roles); + let collection: boolean[] = []; - roleNames.forEach((roleName) => { - let stateName = guild.roles.cache.find((r) => r.name === roleName); - let stateId = guild.roles.cache.find((r) => r.id === roles[roleName]); + for (const group of await dbQuery()) { + for (const element of group) { + const name = guild.roles.cache.find((r) => r.name === element.ROLE_NAME); + const id = guild.roles.cache.find((r) => r.id === element.ROLE_ID); - if (!stateName && !stateId) { - console.log(chalk.red.bold(`Role ${roleName} does not exist in ${guild.name}, Please run the /createRoles command in that server.`)); - collection.push(false); + if (name == undefined && id == undefined) { + console.log(chalk.red.bold(`Role ${name} does not exist in ${guild.name}, Please run the /createRoles command in that server.`)); + collection.push(false); + } } - }); - + } if (collection.includes(false)) { return false; } else { - console.log(chalk.yellow.bold(`All roles in list ${listID} exist in ${guild.name}`)); + console.log(chalk.yellow.bold(`All roles in list exist in ${guild.name}`)); return true; } } From 5cd82e806163ed1965082744cb06c572538d0e71 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 30 Aug 2022 19:40:15 -0500 Subject: [PATCH 18/33] re-add prettier --- .github/workflows/format.yml | 20 ++++++++++++++++++++ .prettierignore | 3 +++ 2 files changed, 23 insertions(+) create mode 100644 .github/workflows/format.yml create mode 100644 .prettierignore diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..dec7807 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,20 @@ +name: Format +on: + pull_request: +jobs: + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + - uses: actions/setup-node@v2 + with: + node-version: ">=16.13.2" + - run: npm ci + - run: npm run format + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Apply auto formatting changes + branch: ${{ github.head_ref }} \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..ef0fed1 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +* +!*.ts +!*/ \ No newline at end of file From 3575cf2b2895fa58aee66e3b76bf2da68ea30728 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Tue, 30 Aug 2022 20:02:49 -0500 Subject: [PATCH 19/33] Merged csClassPoll and csClassTest Sorted classes when pulling from mongo --- commands/owner/csClassTest.ts | 245 +++++++++++++++++++++++----------- 1 file changed, 164 insertions(+), 81 deletions(-) diff --git a/commands/owner/csClassTest.ts b/commands/owner/csClassTest.ts index 459758c..8ed3d1a 100644 --- a/commands/owner/csClassTest.ts +++ b/commands/owner/csClassTest.ts @@ -1,88 +1,171 @@ -import { MessageEmbed, MessageActionRow, MessageSelectMenu } from "discord.js"; +import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; import chalk from "chalk"; import { ICommand } from "wokcommands"; import classModel from "../../models/classModel"; import { checkForRoles } from "../../rolesOps"; +export interface Class { + CODE: string, + TITLE: string, + INFO: string, + ROLE_NAME: string, + ROLE_ID: string, + UUID: string, +} + export default { - name: "csclasstest", - category: "owner", - description: "Posts the Cs Class Poll", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, - - callback: async ({ client, interaction: msgInt }) => { - if (!checkForRoles(msgInt.guild!)) { - msgInt.reply("Please run the `/ createRoles` command in this server to create the necessary roles for this poll!"); - return - } - - const classes = await classModel.find({}); - - console.log(`Number of classes ${classes.length}`); - - const row = new MessageActionRow(); - const row2 = new MessageActionRow(); - let menu = new MessageSelectMenu(); //! this might need to be a `let` - let menu2 = new MessageSelectMenu(); - row.addComponents(menu); - row2.addComponents(menu2); - menu.setCustomId(`csClassPoll+0`); - menu2.setCustomId(`csClassPoll+1`); - menu.setPlaceholder("Select an option"); - menu2.setPlaceholder("Select an option"); - - while (menu.options.length <= 25) { - console.log(menu.options.length); - const label = classes[menu.options.length].CODE as string; - const value = classes[menu.options.length].UUID as string; - const description = classes[menu.options.length].TITLE as string; - menu.addOptions({ - label: label, - value: value, - description: description, - }); - } - if (menu.options.length >= 25) { - while (menu2.options.length < 25 && classes.length > menu2.options.length) { - console.log(menu2.options.length); - const label = classes[menu2.options.length + 24].CODE as string; - const value = classes[menu2.options.length + 24].UUID as string; - const description = classes[menu2.options.length + 24].TITLE as string; - menu2.addOptions({ - label: label, - value: value, - description: description, - }); - } - } - // Define embeds used in this command - const infoEmbed = new MessageEmbed() - .setTitle("Choose a role") - .setColor("#0099ff") - .setDescription("Select the option(s) with your current COMPSCI classes.") - .setFooter({ - text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - }); - - if (menu2.options.length > 1) { - msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); - msgInt.channel?.send({ content: "test", components: [row2] }); - } else { - msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); - - // Log the command usage - console.log( - chalk.blue( - `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green( - `/csclasspoll` - )} command in ${chalk.yellow(msgInt.guild?.name)}` - ) - ); - } - }, + name: "csclasstest", + category: "owner", + description: "Posts the Cs Class Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, + + callback: async ({ client, interaction: msgInt }) => { + if (!checkForRoles(msgInt.guild!)) { + msgInt.reply( + "Please run the `/ createRoles` command in this server to create the necessary roles for this poll!" + ); + return; + } + + let classes: Class[] = await classModel.find({}); + // TODO: See if sorting can be done by mongodb + classes = classes.sort((a, b) => { + const codeA = a.CODE.toUpperCase(); + const codeB = b.CODE.toUpperCase(); + if (codeA < codeB) { + return -1; + } + if (codeB < codeA) { + return 1; + } + return 0; + }); + + console.log(`Number of classes ${classes.length}`); + + const class_chunks = split_list(classes, 25); + + //TODO: remove logging + console.log(`Number of chunks: ${class_chunks.length}`); + //TODO: remove logging + class_chunks.forEach((class_chunk, index) => { + console.log(`Chunk: ${index + 1},\t length: ${class_chunk.length}`); + }); + class_chunks.forEach((class_chunk, index) => { + const menu = new MessageSelectMenu(); + menu.setCustomId(`csClassPoll+${index}`); + menu.setPlaceholder("Select an option"); + // create a new list of options from the classes and add to menu + menu.addOptions(class_chunk.map(create_option_from_class)); + + // Add single message to action row + const row = new MessageActionRow(); + row.addComponents(menu); + + if (index == 0) { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription( + "Select the option(s) with your current COMPSCI classes." + ) + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); + + msgInt.reply({ embeds: [infoEmbed], components: [row] }); + } else { + msgInt.channel!.send({ components: [row] }); + } + }); + + // const row = new MessageActionRow(); + // const row2 = new MessageActionRow(); + // let menu = new MessageSelectMenu(); //! this might need to be a `let` + // let menu2 = new MessageSelectMenu(); + // row.addComponents(menu); + // row2.addComponents(menu2); + // menu.setCustomId(`csClassPoll+0`); + // menu2.setCustomId(`csClassPoll+1`); + // menu.setPlaceholder("Select an option"); + // menu2.setPlaceholder("Select an option"); + + // while (menu.options.length <= 25) { + // console.log(menu.options.length); + // const label = classes[menu.options.length].CODE as string; + // const value = classes[menu.options.length].UUID as string; + // const description = classes[menu.options.length].TITLE as string; + // menu.addOptions({ + // label: label, + // value: value, + // description: description, + // }); + // } + // if (menu.options.length >= 25) { + // while (menu2.options.length < 25 && classes.length > menu2.options.length) { + // console.log(menu2.options.length); + // const label = classes[menu2.options.length + 24].CODE as string; + // const value = classes[menu2.options.length + 24].UUID as string; + // const description = classes[menu2.options.length + 24].TITLE as string; + // menu2.addOptions({ + // label: label, + // value: value, + // description: description, + // }); + // } + // } + // // Define embeds used in this command + // const infoEmbed = new MessageEmbed() + // .setTitle("Choose a role") + // .setColor("#0099ff") + // .setDescription("Select the option(s) with your current COMPSCI classes.") + // .setFooter({ + // text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + // iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + // }); + + // if (menu2.options.length > 1) { + // msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); + // msgInt.channel?.send({ content: "test", components: [row2] }); + // } else { + // msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); + // } + + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + msgInt.user.tag + )} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( + msgInt.guild?.name + )}` + ) + ); + }, } as ICommand; + +// Splits any size list into lists of at most `max_list_len` +function split_list(list: Array, max_list_len: number) { + let class_chunks = [] + for (let i = 0; i < list.length; i += max_list_len) { + class_chunks.push(list.slice(i, i + max_list_len)) + + } + return class_chunks +} + +// consumes a Class and returns Message Selec tOption data +function create_option_from_class(_class: Class): MessageSelectOptionData { + return { + label: _class.CODE, + value: _class.UUID, + description: _class.TITLE, + } +} + From 921d2d216f7ca07aaf5ea42bd3f8864061ed5b2b Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 30 Aug 2022 21:39:09 -0500 Subject: [PATCH 20/33] Lil Update --- commands/owner/csClassPoll.ts | 184 ++++++++++++++++------------------ commands/owner/csClassTest.ts | 171 ------------------------------- rolesOps.ts | 8 +- 3 files changed, 89 insertions(+), 274 deletions(-) delete mode 100644 commands/owner/csClassTest.ts diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index ac03001..d6089aa 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -1,112 +1,98 @@ -// import chalk from "chalk"; -// import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; -// import { ICommand } from "wokcommands"; -// export interface Class { -// code: string, -// title: string, -// info: string, -// roleId: string, -// } +import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; +import chalk from "chalk"; +import { ICommand } from "wokcommands"; +import classModel from "../../models/classModel"; +import { checkForRoles } from "../../rolesOps"; -// export default { -// name: "csClassPoll", -// category: "owner", -// description: "Posts the Cs Class Poll", -// slash: true, -// testOnly: false, -// guildOnly: true, -// requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], -// ownerOnly: true, +export interface Class { + CODE: string, + TITLE: string, + INFO: string, + ROLE_NAME: string, + ROLE_ID: string, + UUID: string, +} -// callback: async ({ client, interaction: msgInt }) => { - +export default { + name: "csClassPoll", + category: "owner", + description: "Posts the CS Class Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, -// // Crashes the call -// // if (!checkForRoles(msgInt.guild!, 2)) { -// // msgInt.reply("Please run the `/ createRoles` command in this server to create the necessary roles for this poll!"); -// // return -// // } + callback: async ({ client, interaction: msgInt }) => { + if (!checkForRoles(msgInt.guild!)) { + msgInt.reply( + "Please run the `/ createRoles` command in this server to create the necessary roles for this poll!" + ); + return; + } -// console.log(`Number of classes ${classes.length}`) + let classes: Class[] = await classModel.find({}).sort({ CODE: 1 }); + const class_chunks = split_list(classes, 25); -// // split classes into chunks of 25 -// const class_chunks: Class[][] = split_list(classes, 25) + class_chunks.forEach((class_chunk, index) => { + const menu = new MessageSelectMenu(); + menu.setCustomId(`csClassPoll+${index}`); + menu.setPlaceholder("Select an option"); + // create a new list of options from the classes and add to menu + menu.addOptions(class_chunk.map(create_option_from_class)); -// //TODO: remove logging -// console.log(`Number of chunks: ${class_chunks.length}`) -// //TODO: remove logging -// class_chunks.forEach( -// (class_chunk, index) => { -// console.log(`Chunk: ${index + 1},\t length: ${class_chunk.length}`) -// } -// ) + // Add single message to action row + const row = new MessageActionRow(); + row.addComponents(menu); -// // Create menus from chunks -// class_chunks.forEach( -// (class_chunk, index) => { -// const menu = new MessageSelectMenu() -// menu.setCustomId(`csClassPoll+${index}`) -// menu.setPlaceholder("Select an option") -// // create a new list of options from the classes and add to menu -// menu.addOptions(class_chunk.map(create_option_from_class)) + if (index == 0) { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription( + "Select the option(s) with your current COMPSCI classes." + ) + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); -// // Add single message to action row -// const row = new MessageActionRow() -// row.addComponents(menu) + msgInt.reply({ embeds: [infoEmbed], components: [row] }); + } else { + msgInt.channel!.send({ components: [row] }); + } + }); -// if (index == 0) { -// // Define embeds used in this command -// const infoEmbed = new MessageEmbed() -// .setTitle("Choose a role") -// .setColor("#0099ff") -// .setDescription("Select the option(s) with your current COMPSCI classes.") -// .setFooter({ -// text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, -// iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", -// }); + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + msgInt.user.tag + )} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( + msgInt.guild?.name + )}` + ) + ); + }, +} as ICommand; -// msgInt.reply({ embeds: [infoEmbed], components: [row] }); -// } -// else { -// msgInt.channel!.send({ components: [row] }); -// } -// } -// ) -// // Log the command usage -// console.log( -// chalk.blue( -// `${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( -// msgInt.guild?.name -// ) -// }` -// ) -// ); -// }, -// } as ICommand; +// Splits any size list into lists of at most `max_list_len` +function split_list(list: Array, max_list_len: number) { + let class_chunks = [] + for (let i = 0; i < list.length; i += max_list_len) { + class_chunks.push(list.slice(i, i + max_list_len)) -// // Splits any size list into lists of at most `max_list_len` -// function split_list(list: Array, max_list_len: number) { -// let class_chunks = [] -// for (let i = 0; i < list.length; i += max_list_len) { -// class_chunks.push(list.slice(i, i + max_list_len)) + } + return class_chunks +} -// } -// return class_chunks -// } - -// // consumes a Class and returns Message Selec tOption data -// function create_option_from_class(_class: Class): MessageSelectOptionData { -// if (_class.code.length > 100) { -// console.log("\n") -// console.log("TOO_LONG: class code") -// console.log(_class) -// console.log("\n") - -// } -// return { -// label: _class.code, -// value: _class.roleId, -// description: _class.title, -// } -// } +// consumes a Class and returns Message Selec tOption data +function create_option_from_class(_class: Class): MessageSelectOptionData { + return { + label: _class.CODE, + value: _class.UUID, + description: _class.TITLE, + } +} diff --git a/commands/owner/csClassTest.ts b/commands/owner/csClassTest.ts deleted file mode 100644 index 8ed3d1a..0000000 --- a/commands/owner/csClassTest.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; -import chalk from "chalk"; -import { ICommand } from "wokcommands"; -import classModel from "../../models/classModel"; -import { checkForRoles } from "../../rolesOps"; - -export interface Class { - CODE: string, - TITLE: string, - INFO: string, - ROLE_NAME: string, - ROLE_ID: string, - UUID: string, -} - -export default { - name: "csclasstest", - category: "owner", - description: "Posts the Cs Class Poll", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, - - callback: async ({ client, interaction: msgInt }) => { - if (!checkForRoles(msgInt.guild!)) { - msgInt.reply( - "Please run the `/ createRoles` command in this server to create the necessary roles for this poll!" - ); - return; - } - - let classes: Class[] = await classModel.find({}); - // TODO: See if sorting can be done by mongodb - classes = classes.sort((a, b) => { - const codeA = a.CODE.toUpperCase(); - const codeB = b.CODE.toUpperCase(); - if (codeA < codeB) { - return -1; - } - if (codeB < codeA) { - return 1; - } - return 0; - }); - - console.log(`Number of classes ${classes.length}`); - - const class_chunks = split_list(classes, 25); - - //TODO: remove logging - console.log(`Number of chunks: ${class_chunks.length}`); - //TODO: remove logging - class_chunks.forEach((class_chunk, index) => { - console.log(`Chunk: ${index + 1},\t length: ${class_chunk.length}`); - }); - class_chunks.forEach((class_chunk, index) => { - const menu = new MessageSelectMenu(); - menu.setCustomId(`csClassPoll+${index}`); - menu.setPlaceholder("Select an option"); - // create a new list of options from the classes and add to menu - menu.addOptions(class_chunk.map(create_option_from_class)); - - // Add single message to action row - const row = new MessageActionRow(); - row.addComponents(menu); - - if (index == 0) { - // Define embeds used in this command - const infoEmbed = new MessageEmbed() - .setTitle("Choose a role") - .setColor("#0099ff") - .setDescription( - "Select the option(s) with your current COMPSCI classes." - ) - .setFooter({ - text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - }); - - msgInt.reply({ embeds: [infoEmbed], components: [row] }); - } else { - msgInt.channel!.send({ components: [row] }); - } - }); - - // const row = new MessageActionRow(); - // const row2 = new MessageActionRow(); - // let menu = new MessageSelectMenu(); //! this might need to be a `let` - // let menu2 = new MessageSelectMenu(); - // row.addComponents(menu); - // row2.addComponents(menu2); - // menu.setCustomId(`csClassPoll+0`); - // menu2.setCustomId(`csClassPoll+1`); - // menu.setPlaceholder("Select an option"); - // menu2.setPlaceholder("Select an option"); - - // while (menu.options.length <= 25) { - // console.log(menu.options.length); - // const label = classes[menu.options.length].CODE as string; - // const value = classes[menu.options.length].UUID as string; - // const description = classes[menu.options.length].TITLE as string; - // menu.addOptions({ - // label: label, - // value: value, - // description: description, - // }); - // } - // if (menu.options.length >= 25) { - // while (menu2.options.length < 25 && classes.length > menu2.options.length) { - // console.log(menu2.options.length); - // const label = classes[menu2.options.length + 24].CODE as string; - // const value = classes[menu2.options.length + 24].UUID as string; - // const description = classes[menu2.options.length + 24].TITLE as string; - // menu2.addOptions({ - // label: label, - // value: value, - // description: description, - // }); - // } - // } - // // Define embeds used in this command - // const infoEmbed = new MessageEmbed() - // .setTitle("Choose a role") - // .setColor("#0099ff") - // .setDescription("Select the option(s) with your current COMPSCI classes.") - // .setFooter({ - // text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - // iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - // }); - - // if (menu2.options.length > 1) { - // msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); - // msgInt.channel?.send({ content: "test", components: [row2] }); - // } else { - // msgInt.channel?.send({ embeds: [infoEmbed], components: [row] }); - // } - - // Log the command usage - console.log( - chalk.blue( - `${chalk.green(`[COMMAND]`)} ${chalk.yellow( - msgInt.user.tag - )} used the ${chalk.green(`/csclasspoll`)} command in ${chalk.yellow( - msgInt.guild?.name - )}` - ) - ); - }, -} as ICommand; - -// Splits any size list into lists of at most `max_list_len` -function split_list(list: Array, max_list_len: number) { - let class_chunks = [] - for (let i = 0; i < list.length; i += max_list_len) { - class_chunks.push(list.slice(i, i + max_list_len)) - - } - return class_chunks -} - -// consumes a Class and returns Message Selec tOption data -function create_option_from_class(_class: Class): MessageSelectOptionData { - return { - label: _class.CODE, - value: _class.UUID, - description: _class.TITLE, - } -} - diff --git a/rolesOps.ts b/rolesOps.ts index e51e28d..9b522de 100644 --- a/rolesOps.ts +++ b/rolesOps.ts @@ -44,15 +44,15 @@ export async function removeRole(member: GuildMember, type: string): Promise Date: Tue, 30 Aug 2022 21:51:51 -0500 Subject: [PATCH 21/33] Ready for testing --- commands/owner/csClassPoll.ts | 2 ++ features/interactionCreate.ts | 4 ---- rolesOps.ts | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index d6089aa..5fcd251 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -37,6 +37,8 @@ export default { class_chunks.forEach((class_chunk, index) => { const menu = new MessageSelectMenu(); menu.setCustomId(`csClassPoll+${index}`); + // menu.setMinValues(1); //!Add this later when the bot is able to handle multiple selections at once + // menu.setMaxValues(10); menu.setPlaceholder("Select an option"); // create a new list of options from the classes and add to menu menu.addOptions(class_chunk.map(create_option_from_class)); diff --git a/features/interactionCreate.ts b/features/interactionCreate.ts index e70dc01..9145486 100644 --- a/features/interactionCreate.ts +++ b/features/interactionCreate.ts @@ -17,10 +17,6 @@ export default (client: Client): void => { if (interaction.customId === "collegeYearPoll") { // Set the embed values const title = "College Year Poll"; - const color = "#0099ff"; - const description = `You selected the ${interaction.values[0]} role.`; - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; // Create and send the embed object interaction.reply({ diff --git a/rolesOps.ts b/rolesOps.ts index 9b522de..ed570ce 100644 --- a/rolesOps.ts +++ b/rolesOps.ts @@ -54,7 +54,7 @@ export async function addNewRole(member: GuildMember, type: string, id: string) } else if (type === "year") { role = await yearModel.findOne({ ROLE_NAME: id }); } - if (member.roles.cache.has(role?.ROLE_ID)) { + if (!member.roles.cache.has(role?.ROLE_ID)) {//testtest await member.roles.add(role?.ROLE_ID); console.log(chalk.green(`Added role ${chalk.green(role.ROLE_NAME)} to ${chalk.yellow(member.user.tag)}`)); } From 4ce68855fad844eaed4d511c3ad3f908aa961bc8 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Tue, 30 Aug 2022 22:48:00 -0500 Subject: [PATCH 22/33] update to use for loop and add delay --- commands/owner/csClassPoll.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 5fcd251..e141756 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -34,14 +34,14 @@ export default { let classes: Class[] = await classModel.find({}).sort({ CODE: 1 }); const class_chunks = split_list(classes, 25); - class_chunks.forEach((class_chunk, index) => { + for(let index = 0; index < class_chunks.length; index ++){ const menu = new MessageSelectMenu(); menu.setCustomId(`csClassPoll+${index}`); // menu.setMinValues(1); //!Add this later when the bot is able to handle multiple selections at once // menu.setMaxValues(10); menu.setPlaceholder("Select an option"); // create a new list of options from the classes and add to menu - menu.addOptions(class_chunk.map(create_option_from_class)); + menu.addOptions(class_chunks[index].map(create_option_from_class)); // Add single message to action row const row = new MessageActionRow(); @@ -64,7 +64,9 @@ export default { } else { msgInt.channel!.send({ components: [row] }); } - }); + // await on a new promise that resolves itself after a delay of 200 ms + await new Promise(resolve => {setTimeout(resolve, 200)}) + }; // Log the command usage console.log( From 3ddbcaa0fb252cb6ccea56b49171d56e72137f10 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Tue, 30 Aug 2022 22:48:15 -0500 Subject: [PATCH 23/33] allow for more than 2 csClassPolls --- features/interactionCreate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/interactionCreate.ts b/features/interactionCreate.ts index 9145486..efe6fdf 100644 --- a/features/interactionCreate.ts +++ b/features/interactionCreate.ts @@ -61,7 +61,7 @@ export default (client: Client): void => { // Assign the new role to the user addNewRole(member, "staff", interaction.values[0]); - } else if (interaction.customId === "csClassPoll+0" || interaction.customId === "csClassPoll+1") { + } else if (interaction.customId.startsWith("csClassPoll+")) { // Set the embed title const title = "CS Class Poll"; // Create and send the embed object From 5c13d4588626a9d66a6b1a044987361c73522f01 Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Tue, 30 Aug 2022 23:05:34 -0500 Subject: [PATCH 24/33] send up to 5 menu's per message --- commands/owner/csClassPoll.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index e141756..84170c7 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -34,7 +34,8 @@ export default { let classes: Class[] = await classModel.find({}).sort({ CODE: 1 }); const class_chunks = split_list(classes, 25); - for(let index = 0; index < class_chunks.length; index ++){ + let rows:MessageActionRow[] = []; + for (let index = 0; index < class_chunks.length; index++) { const menu = new MessageSelectMenu(); menu.setCustomId(`csClassPoll+${index}`); // menu.setMinValues(1); //!Add this later when the bot is able to handle multiple selections at once @@ -46,7 +47,12 @@ export default { // Add single message to action row const row = new MessageActionRow(); row.addComponents(menu); + rows.push(row); + } + + const row_chunks = split_list(rows, 5) + for (let index = 0; index < row_chunks.length; index++) { if (index == 0) { // Define embeds used in this command const infoEmbed = new MessageEmbed() @@ -60,13 +66,15 @@ export default { iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", }); - msgInt.reply({ embeds: [infoEmbed], components: [row] }); + msgInt.reply({ embeds: [infoEmbed], components: row_chunks[index] }); } else { - msgInt.channel!.send({ components: [row] }); + msgInt.channel!.send({ components: row_chunks[index] }); } - // await on a new promise that resolves itself after a delay of 200 ms - await new Promise(resolve => {setTimeout(resolve, 200)}) - }; + // await on a new promise that resolves itself after a delay of 200 ms + await new Promise((resolve) => { + setTimeout(resolve, 200); + }); + } // Log the command usage console.log( From f2a7407784856ed050a17ef4745aa773f083343e Mon Sep 17 00:00:00 2001 From: John Schiltz Date: Tue, 30 Aug 2022 23:29:25 -0500 Subject: [PATCH 25/33] switch to using class CODE as key rather than suuid This only works wile the codes are unique --- commands/owner/csClassPoll.ts | 2 +- package-lock.json | 45 ----------------------------------- package.json | 3 +-- rolesOps.ts | 2 +- 4 files changed, 3 insertions(+), 49 deletions(-) diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index 84170c7..ce970e6 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -103,7 +103,7 @@ function split_list(list: Array, max_list_len: number) { function create_option_from_class(_class: Class): MessageSelectOptionData { return { label: _class.CODE, - value: _class.UUID, + value: _class.CODE, description: _class.TITLE, } } diff --git a/package-lock.json b/package-lock.json index a70909a..20d3f34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "discord.js": "^13.9.2", "mongoose": "^6.2.2", "path": "^0.12.7", - "short-uuid": "^4.2.0", "ts-node": "^10.5.0", "typescript": "^4.5.5", "wokcommands": "^1.5.3" @@ -210,11 +209,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", - "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -672,18 +666,6 @@ "node": ">=6" } }, - "node_modules/short-uuid": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/short-uuid/-/short-uuid-4.2.0.tgz", - "integrity": "sha512-r3cxuPPZSuF0QkKsK9bBR7u+7cwuCRzWzgjPh07F5N2iIUNgblnMHepBY16xgj5t1lG9iOP9k/TEafY1qhRzaw==", - "dependencies": { - "any-base": "^1.1.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/sift": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", @@ -814,14 +796,6 @@ "inherits": "2.0.3" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -1038,11 +1012,6 @@ "color-convert": "^2.0.1" } }, - "any-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", - "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" - }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -1359,15 +1328,6 @@ "sparse-bitfield": "^3.0.3" } }, - "short-uuid": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/short-uuid/-/short-uuid-4.2.0.tgz", - "integrity": "sha512-r3cxuPPZSuF0QkKsK9bBR7u+7cwuCRzWzgjPh07F5N2iIUNgblnMHepBY16xgj5t1lG9iOP9k/TEafY1qhRzaw==", - "requires": { - "any-base": "^1.1.0", - "uuid": "^8.3.2" - } - }, "sift": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", @@ -1455,11 +1415,6 @@ "inherits": "2.0.3" } }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index f96f811..7954d10 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,8 @@ "discord.js": "^13.9.2", "mongoose": "^6.2.2", "path": "^0.12.7", - "short-uuid": "^4.2.0", "ts-node": "^10.5.0", "typescript": "^4.5.5", "wokcommands": "^1.5.3" } -} \ No newline at end of file +} diff --git a/rolesOps.ts b/rolesOps.ts index ed570ce..67c0fc1 100644 --- a/rolesOps.ts +++ b/rolesOps.ts @@ -48,7 +48,7 @@ export async function addNewRole(member: GuildMember, type: string, id: string) // This function is triggered when a user changes their role, it adds the new role to the user let role; if (type === "class") { - role = await classModel.findOne({ UUID: id }); + role = await classModel.findOne({ CODE: id }); } else if (type === "staff") { role = await staffModel.findOne({ ROLE_NAME: id }); } else if (type === "year") { From a224a3493b05ab0460135b6960532d6ab2a46091 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Tue, 30 Aug 2022 23:36:04 -0500 Subject: [PATCH 26/33] Minor Updates --- commands/owner/createRoles.ts | 2 +- commands/user/{clearRoles.ts => clear.ts} | 0 commands/user/{viewRoles.ts => view.ts} | 0 rolesOps.ts | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename commands/user/{clearRoles.ts => clear.ts} (100%) rename commands/user/{viewRoles.ts => view.ts} (100%) diff --git a/commands/owner/createRoles.ts b/commands/owner/createRoles.ts index 4fb1286..c8320b7 100644 --- a/commands/owner/createRoles.ts +++ b/commands/owner/createRoles.ts @@ -20,7 +20,7 @@ export default { createRoles(interaction.guild!, "staff"); createRoles(interaction.guild!, "year"); interaction.reply({ - content: "Roles created! Check the console for the role IDs\nPaste the output into your .env file and restart the bot\n ", + content: "Roles created!", ephemeral: true, }); diff --git a/commands/user/clearRoles.ts b/commands/user/clear.ts similarity index 100% rename from commands/user/clearRoles.ts rename to commands/user/clear.ts diff --git a/commands/user/viewRoles.ts b/commands/user/view.ts similarity index 100% rename from commands/user/viewRoles.ts rename to commands/user/view.ts diff --git a/rolesOps.ts b/rolesOps.ts index 67c0fc1..ff49ff3 100644 --- a/rolesOps.ts +++ b/rolesOps.ts @@ -17,7 +17,7 @@ export async function getUsersRoles(member: GuildMember): Promise { for (const group of await dbQuery()) { for (const element of group) { if (member.roles.cache.has(element.ROLE_ID)) { - list += `${member.guild.roles.cache.get(element.ROLE_NAME)?.name}\n`; + list += `${member.guild.roles.cache.get(element.ROLE_ID)?.name}\n`; } } } From 18d6f73da739ee3820a60ee877066dbbf9b6f8ec Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Thu, 1 Sep 2022 12:41:01 -0500 Subject: [PATCH 27/33] Bugfix and add docker workflow --- .github/workflows/publish-docker-image.yml | 22 ++++++++++++++++++++++ commands/owner/yearPoll.ts | 2 +- models/classModel.ts | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish-docker-image.yml diff --git a/.github/workflows/publish-docker-image.yml b/.github/workflows/publish-docker-image.yml new file mode 100644 index 0000000..fda9993 --- /dev/null +++ b/.github/workflows/publish-docker-image.yml @@ -0,0 +1,22 @@ +name: Publish Docker image to GitHub Package Registry +on: push +jobs: + build: + runs-on: ubuntu-latest + steps: + + - name: Copy Repo Files + uses: actions/checkout@master + + #This Action Emits 2 Variables, IMAGE_SHA_NAME and IMAGE_URL + #which you can reference in subsequent steps + - name: Publish Docker Image to GPR + uses: machine-learning-apps/gpr-docker-publish@master + id: docker + with: + IMAGE_NAME: 'cssc-bot' + TAG: 'latest' + DOCKERFILE_PATH: './Dockerfile' + BUILD_CONTEXT: 'argo/' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/commands/owner/yearPoll.ts b/commands/owner/yearPoll.ts index 07b43cc..d90126a 100644 --- a/commands/owner/yearPoll.ts +++ b/commands/owner/yearPoll.ts @@ -52,7 +52,7 @@ export default { value: "Senior", }, { - label: "Graduate Student", + label: "Grad Student", value: "Graduatestudent", }, { diff --git a/models/classModel.ts b/models/classModel.ts index 48fb55d..fbcf549 100644 --- a/models/classModel.ts +++ b/models/classModel.ts @@ -7,6 +7,8 @@ const CLASS = new Schema({ INFO: String, ROLE_NAME: String, ROLE_ID: String, + CHANNEL_NAME: String, + CHANNEL_ID: String, UUID: String }); From 7dc24544fdcc81d6be8d7e4e9c1d82098ff1277a Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Thu, 1 Sep 2022 13:35:51 -0500 Subject: [PATCH 28/33] Bug fix --- rolesOps.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rolesOps.ts b/rolesOps.ts index ff49ff3..d390781 100644 --- a/rolesOps.ts +++ b/rolesOps.ts @@ -50,11 +50,11 @@ export async function addNewRole(member: GuildMember, type: string, id: string) if (type === "class") { role = await classModel.findOne({ CODE: id }); } else if (type === "staff") { - role = await staffModel.findOne({ ROLE_NAME: id }); + role = await staffModel.findOne({ NAME: id }); } else if (type === "year") { - role = await yearModel.findOne({ ROLE_NAME: id }); + role = await yearModel.findOne({ NAME: id }); } - if (!member.roles.cache.has(role?.ROLE_ID)) {//testtest + if (!member.roles.cache.has(role?.ROLE_ID)) { await member.roles.add(role?.ROLE_ID); console.log(chalk.green(`Added role ${chalk.green(role.ROLE_NAME)} to ${chalk.yellow(member.user.tag)}`)); } From c82b1b5408e3924ef22b403f09cc89d4b3757cf0 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Thu, 1 Sep 2022 13:37:27 -0500 Subject: [PATCH 29/33] Remove argo path --- .github/workflows/publish-docker-image.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/publish-docker-image.yml b/.github/workflows/publish-docker-image.yml index fda9993..3cd47ad 100644 --- a/.github/workflows/publish-docker-image.yml +++ b/.github/workflows/publish-docker-image.yml @@ -17,6 +17,5 @@ jobs: IMAGE_NAME: 'cssc-bot' TAG: 'latest' DOCKERFILE_PATH: './Dockerfile' - BUILD_CONTEXT: 'argo/' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 8fa589372b097fa3d3e553c60a6f4940da6d07f4 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Thu, 1 Sep 2022 13:39:40 -0500 Subject: [PATCH 30/33] add prettier script --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7954d10..6fcd6ea 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "cssc-bot", - "version": "2.1.0", + "version": "2.2.0", "engines": { "node": "17.x" }, "description": "", "main": "index.ts", "scripts": { - "run": "ts-node index.ts" + "run": "ts-node index.ts", + "format": "prettier --write ." }, "repository": { "type": "git", From 1fe93e2a48f2e43b5cf030a3ff692a0136c153ba Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Thu, 1 Sep 2022 13:41:28 -0500 Subject: [PATCH 31/33] install prettier --- package-lock.json | 24 ++++++++++++++++++++++-- package.json | 3 ++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 20d3f34..059f41a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cssc-bot", - "version": "2.1.0", + "version": "2.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cssc-bot", - "version": "2.1.0", + "version": "2.2.0", "license": "ISC", "dependencies": { "axios": "^0.27.2", @@ -14,6 +14,7 @@ "discord.js": "^13.9.2", "mongoose": "^6.2.2", "path": "^0.12.7", + "prettier": "^2.7.1", "ts-node": "^10.5.0", "typescript": "^4.5.5", "wokcommands": "^1.5.3" @@ -638,6 +639,20 @@ "util": "^0.10.3" } }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -1309,6 +1324,11 @@ "util": "^0.10.3" } }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==" + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", diff --git a/package.json b/package.json index 6fcd6ea..e04d259 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "type": "git", "url": "git+https://github.com/Antares-Network/CSSC-Bot.git" }, - "author": "llisaeva, nathen418", + "author": "llisaeva, nathen418, schiltz3", "license": "ISC", "bugs": { "url": "https://github.com/Antares-Network/CSSC-Bot/issues" @@ -26,6 +26,7 @@ "discord.js": "^13.9.2", "mongoose": "^6.2.2", "path": "^0.12.7", + "prettier": "^2.7.1", "ts-node": "^10.5.0", "typescript": "^4.5.5", "wokcommands": "^1.5.3" From 470445a895984f568bdded711f26f91aa2b05cca Mon Sep 17 00:00:00 2001 From: nathen418 Date: Thu, 1 Sep 2022 18:41:55 +0000 Subject: [PATCH 32/33] Apply auto formatting changes --- commands/owner/createRoles.ts | 64 ++++++----- commands/owner/csClassPoll.ts | 34 +++--- commands/owner/say.ts | 44 +++++--- commands/owner/staffPoll.ts | 130 ++++++++++++---------- commands/owner/yearPoll.ts | 149 +++++++++++++------------ commands/user/clear.ts | 49 +++++---- commands/user/github.ts | 62 ++++++----- commands/user/help.ts | 125 +++++++++++---------- commands/user/ping.ts | 62 ++++++----- commands/user/status.ts | 62 ++++++----- commands/user/uptime.ts | 28 +++-- commands/user/version.ts | 62 ++++++----- commands/user/view.ts | 25 +++-- features/interactionCreate.ts | 148 ++++++++++++------------- features/status-changer.ts | 69 ++++++------ features/statuspage.ts | 24 ++-- index.ts | 87 ++++++++------- models/classModel.ts | 18 +-- models/staffModel.ts | 8 +- models/yearModel.ts | 9 +- rolesOps.ts | 200 +++++++++++++++++++--------------- 21 files changed, 799 insertions(+), 660 deletions(-) diff --git a/commands/owner/createRoles.ts b/commands/owner/createRoles.ts index c8320b7..992c297 100644 --- a/commands/owner/createRoles.ts +++ b/commands/owner/createRoles.ts @@ -3,34 +3,42 @@ import { createRoles } from "../../rolesOps"; import chalk from "chalk"; export default { - name: "createRoles", - category: "owner", - description: "Creates roles if they do not exist in the server", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, + name: "createRoles", + category: "owner", + description: "Creates roles if they do not exist in the server", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, - callback: async ({ interaction }) => { - console.log(chalk.green("Creating roles...\nCopy and paste the following output into your .env file")); - console.log(chalk.red("------------------------------------------------------")); - // Create the roles - createRoles(interaction.guild!, "class"); - createRoles(interaction.guild!, "staff"); - createRoles(interaction.guild!, "year"); - interaction.reply({ - content: "Roles created!", - ephemeral: true, - }); + callback: async ({ interaction }) => { + console.log( + chalk.green( + "Creating roles...\nCopy and paste the following output into your .env file" + ) + ); + console.log( + chalk.red("------------------------------------------------------") + ); + // Create the roles + createRoles(interaction.guild!, "class"); + createRoles(interaction.guild!, "staff"); + createRoles(interaction.guild!, "year"); + interaction.reply({ + content: "Roles created!", + ephemeral: true, + }); - // Log the command usage - console.log( - chalk.blue( - `${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/yearPoll`)} command in ${chalk.yellow( - interaction.guild?.name - )}` - ) - ); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/yearPoll`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/owner/csClassPoll.ts b/commands/owner/csClassPoll.ts index ce970e6..6bee095 100644 --- a/commands/owner/csClassPoll.ts +++ b/commands/owner/csClassPoll.ts @@ -1,16 +1,21 @@ -import { MessageEmbed, MessageActionRow, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; +import { + MessageEmbed, + MessageActionRow, + MessageSelectMenu, + MessageSelectOptionData, +} from "discord.js"; import chalk from "chalk"; import { ICommand } from "wokcommands"; import classModel from "../../models/classModel"; import { checkForRoles } from "../../rolesOps"; export interface Class { - CODE: string, - TITLE: string, - INFO: string, - ROLE_NAME: string, - ROLE_ID: string, - UUID: string, + CODE: string; + TITLE: string; + INFO: string; + ROLE_NAME: string; + ROLE_ID: string; + UUID: string; } export default { @@ -34,7 +39,7 @@ export default { let classes: Class[] = await classModel.find({}).sort({ CODE: 1 }); const class_chunks = split_list(classes, 25); - let rows:MessageActionRow[] = []; + let rows: MessageActionRow[] = []; for (let index = 0; index < class_chunks.length; index++) { const menu = new MessageSelectMenu(); menu.setCustomId(`csClassPoll+${index}`); @@ -50,8 +55,7 @@ export default { rows.push(row); } - - const row_chunks = split_list(rows, 5) + const row_chunks = split_list(rows, 5); for (let index = 0; index < row_chunks.length; index++) { if (index == 0) { // Define embeds used in this command @@ -91,12 +95,11 @@ export default { // Splits any size list into lists of at most `max_list_len` function split_list(list: Array, max_list_len: number) { - let class_chunks = [] + let class_chunks = []; for (let i = 0; i < list.length; i += max_list_len) { - class_chunks.push(list.slice(i, i + max_list_len)) - + class_chunks.push(list.slice(i, i + max_list_len)); } - return class_chunks + return class_chunks; } // consumes a Class and returns Message Selec tOption data @@ -105,6 +108,5 @@ function create_option_from_class(_class: Class): MessageSelectOptionData { label: _class.CODE, value: _class.CODE, description: _class.TITLE, - } + }; } - diff --git a/commands/owner/say.ts b/commands/owner/say.ts index bda5122..c7bab8d 100644 --- a/commands/owner/say.ts +++ b/commands/owner/say.ts @@ -20,25 +20,41 @@ export default { type: DiscordJS.Constants.ApplicationCommandOptionTypes.STRING, required: true, }, - { - name: "channel", - description: "The channel to say the thing in", - type: DiscordJS.Constants.ApplicationCommandOptionTypes.CHANNEL, - required: false, - } - ], + { + name: "channel", + description: "The channel to say the thing in", + type: DiscordJS.Constants.ApplicationCommandOptionTypes.CHANNEL, + required: false, + }, + ], callback: ({ interaction }) => { const content = interaction.options.getString("content") as string; - const channel = interaction.options.getChannel("channel") as TextChannel || interaction.channel as TextChannel; + const channel = + (interaction.options.getChannel("channel") as TextChannel) || + (interaction.channel as TextChannel); if (!content) { - interaction.reply({ content: "You need to provide a content to say", ephemeral: true }); - return; + interaction.reply({ + content: "You need to provide a content to say", + ephemeral: true, + }); + return; } channel.send(content); - interaction.reply({ content: `Message sent in <#${channel.id}>`, ephemeral: true }); + interaction.reply({ + content: `Message sent in <#${channel.id}>`, + ephemeral: true, + }); // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/say`)} command in ${chalk.yellow(interaction.guild?.name)}`)); - } -} as ICommand; \ No newline at end of file + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/say`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, +} as ICommand; diff --git a/commands/owner/staffPoll.ts b/commands/owner/staffPoll.ts index f6ca37a..c35d75c 100644 --- a/commands/owner/staffPoll.ts +++ b/commands/owner/staffPoll.ts @@ -4,68 +4,78 @@ import { ICommand } from "wokcommands"; import { checkForRoles } from "../../rolesOps"; export default { - name: "staffPoll", - category: "owner", - description: "Posts the College Staff Poll", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, + name: "staffPoll", + category: "owner", + description: "Posts the College Staff Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, - callback: async ({ client, interaction: msgInt }) => { - // Define embeds used in this command - const infoEmbed = new MessageEmbed() - .setTitle("Choose a role") - .setColor("#0099ff") - .setDescription("Select the option with your current occupation at UWM.") - .setFooter({ - text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - }); + callback: async ({ client, interaction: msgInt }) => { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the option with your current occupation at UWM.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); - // Create row one of the buttons for the poll - const row = new MessageActionRow().addComponents( - new MessageSelectMenu() - .setCustomId("collegeStaffPoll") - .setPlaceholder("Select an option") - .addOptions( - { - label: "Tutor", - value: "Tutor", - }, - { - label: "SI Leader", - value: "Sileader", - }, - { - label: "TA", - value: "Ta", - }, - { - label: "Professor", - value: "Professor", - }, - { - label: "Student Employee", - value: "Studentemployee", - }, - { - label: "None", - value: "None", - description: "Clear all staff roles", - } - ) - ); + // Create row one of the buttons for the poll + const row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setCustomId("collegeStaffPoll") + .setPlaceholder("Select an option") + .addOptions( + { + label: "Tutor", + value: "Tutor", + }, + { + label: "SI Leader", + value: "Sileader", + }, + { + label: "TA", + value: "Ta", + }, + { + label: "Professor", + value: "Professor", + }, + { + label: "Student Employee", + value: "Studentemployee", + }, + { + label: "None", + value: "None", + description: "Clear all staff roles", + } + ) + ); - // Send the embed and message component rows - if (!checkForRoles(msgInt.guild!)) { - msgInt.reply("Please run the `/createRoles` command in this server to create the necessary roles for this poll!"); - } else { - msgInt.reply({ embeds: [infoEmbed], components: [row] }); - } + // Send the embed and message component rows + if (!checkForRoles(msgInt.guild!)) { + msgInt.reply( + "Please run the `/createRoles` command in this server to create the necessary roles for this poll!" + ); + } else { + msgInt.reply({ embeds: [infoEmbed], components: [row] }); + } - // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/staffPoll`)} command in ${chalk.yellow(msgInt.guild?.name)}`)); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + msgInt.user.tag + )} used the ${chalk.green(`/staffPoll`)} command in ${chalk.yellow( + msgInt.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/owner/yearPoll.ts b/commands/owner/yearPoll.ts index d90126a..17f6e62 100644 --- a/commands/owner/yearPoll.ts +++ b/commands/owner/yearPoll.ts @@ -4,77 +4,88 @@ import { ICommand } from "wokcommands"; import { checkForRoles } from "../../rolesOps"; export default { - name: "yearPoll", - category: "owner", - description: "Posts the College Year Poll", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], - ownerOnly: true, + name: "yearPoll", + category: "owner", + description: "Posts the College Year Poll", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["MANAGE_GUILD", "MANAGE_ROLES"], + ownerOnly: true, - callback: async ({ client, interaction: msgInt }) => { - // Define embeds used in this command - const infoEmbed = new MessageEmbed() - .setTitle("Choose a role") - .setColor("#0099ff") - .setDescription("Select the button with your current college year.") - .setFooter({ - text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, - iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", - }); + callback: async ({ client, interaction: msgInt }) => { + // Define embeds used in this command + const infoEmbed = new MessageEmbed() + .setTitle("Choose a role") + .setColor("#0099ff") + .setDescription("Select the button with your current college year.") + .setFooter({ + text: `Delivered in: ${client.ws.ping}ms | CSSC-Bot | ${process.env.VERSION}`, + iconURL: "https://playantares.com/resources/CSSC-bot/icon.jpg", + }); - - // Create row one of the buttons for the poll - const row = new MessageActionRow().addComponents( - new MessageSelectMenu() - .setCustomId("collegeYearPoll") - .setPlaceholder("Select an option.") - .addOptions( - { - label: "Prefrosh", - value: "Prefrosh", - }, - { - label: "Freshman", - value: "Freshman", - }, - { - label: "Sophomore", - value: "Sophomore", - }, - { - label: "Junior", - value: "Junior", - }, - { - label: "Senior", - value: "Senior", - }, - { - label: "Grad Student", - value: "Graduatestudent", - }, - { - label: "Alumni", - value: "Alumni", - }, - { - label: "None", - value: "None", - description: "Clear all year roles", - } - ) - ); + // Create row one of the buttons for the poll + const row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setCustomId("collegeYearPoll") + .setPlaceholder("Select an option.") + .addOptions( + { + label: "Prefrosh", + value: "Prefrosh", + }, + { + label: "Freshman", + value: "Freshman", + }, + { + label: "Sophomore", + value: "Sophomore", + }, + { + label: "Junior", + value: "Junior", + }, + { + label: "Senior", + value: "Senior", + }, + { + label: "Grad Student", + value: "Graduatestudent", + }, + { + label: "Alumni", + value: "Alumni", + }, + { + label: "None", + value: "None", + description: "Clear all year roles", + } + ) + ); - // Send the embed and message component rows - if (!checkForRoles(msgInt.guild!)) { - msgInt.reply({content: "Please run the /createRoles command in this server to create the necessary roles for this poll!", ephemeral: true}); - } else { - msgInt.reply({ embeds: [infoEmbed], components: [row] }); - } + // Send the embed and message component rows + if (!checkForRoles(msgInt.guild!)) { + msgInt.reply({ + content: + "Please run the /createRoles command in this server to create the necessary roles for this poll!", + ephemeral: true, + }); + } else { + msgInt.reply({ embeds: [infoEmbed], components: [row] }); + } - // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(msgInt.user.tag)} used the ${chalk.green(`/yearPoll`)} command in ${chalk.yellow(msgInt.guild?.name)}`)); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + msgInt.user.tag + )} used the ${chalk.green(`/yearPoll`)} command in ${chalk.yellow( + msgInt.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/user/clear.ts b/commands/user/clear.ts index 6f41e84..207b792 100644 --- a/commands/user/clear.ts +++ b/commands/user/clear.ts @@ -4,25 +4,36 @@ import { ICommand } from "wokcommands"; import { removeRole } from "../../rolesOps"; export default { - name: "clear", - category: "user", - description: "removes all roles the bot has assigned to a user", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["SEND_MESSAGES"], + name: "clear", + category: "user", + description: "removes all roles the bot has assigned to a user", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], - callback: async ({ interaction }) => { - // Remove roles from user - if (!interaction.member) return; - const member = interaction.member as GuildMember; - removeRole(member, "class"); - removeRole(member, "year"); - removeRole(member, "staff"); - // Reply to the user - interaction.reply({ content: "Cleared all roles that I have assigned to you.", ephemeral: true }); + callback: async ({ interaction }) => { + // Remove roles from user + if (!interaction.member) return; + const member = interaction.member as GuildMember; + removeRole(member, "class"); + removeRole(member, "year"); + removeRole(member, "staff"); + // Reply to the user + interaction.reply({ + content: "Cleared all roles that I have assigned to you.", + ephemeral: true, + }); - // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/clear`)} command in ${chalk.yellow(interaction.guild?.name)}`)); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/clear`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/user/github.ts b/commands/user/github.ts index 32641d1..9ca20fe 100644 --- a/commands/user/github.ts +++ b/commands/user/github.ts @@ -3,34 +3,44 @@ import { MessageEmbed } from "discord.js"; import { ICommand } from "wokcommands"; export default { - name: "github", - category: "user", - description: "Sends an embed with a link to the github repo for the bot.", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["SEND_MESSAGES"], + name: "github", + category: "user", + description: "Sends an embed with a link to the github repo for the bot.", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], - callback: async ({ client, interaction }) => { - // Embed values - const color = "#0099ff"; - const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; - const title = "Github"; - const description = "Click here to go to the CSSC-bot repo: \n https://github.com/Antares-Network/CSSC-Bot"; - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + callback: async ({ client, interaction }) => { + // Embed values + const color = "#0099ff"; + const thumbnail = + "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; + const title = "Github"; + const description = + "Click here to go to the CSSC-bot repo: \n https://github.com/Antares-Network/CSSC-Bot"; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; - // Embed construction - const Embed = new MessageEmbed() - .setColor(color) - .setTitle(title) - .setThumbnail(thumbnail) - .setDescription(description) - .setFooter({ text: footer, iconURL: footerIcon }); + // Embed construction + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setThumbnail(thumbnail) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }); - interaction.reply({ embeds: [Embed] }); + interaction.reply({ embeds: [Embed] }); - // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/github`)} command in ${chalk.yellow(interaction.guild?.name)}`)); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/github`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/user/help.ts b/commands/user/help.ts index a4194e6..3c3030e 100644 --- a/commands/user/help.ts +++ b/commands/user/help.ts @@ -1,62 +1,69 @@ import chalk from "chalk"; -import { - MessageEmbed, - } from "discord.js"; - import { ICommand } from "wokcommands"; - - export default { - name: "help", - category: "user", - description: "Shows the help embed", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["SEND_MESSAGES"], - - callback: async ({ client, interaction }) => { +import { MessageEmbed } from "discord.js"; +import { ICommand } from "wokcommands"; - const color = "#0099ff" ; - const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; - const title = "Help and Commands List"; - const description = "Welcome to CSSC-Bot! My purpose in this server is to make sure you have the correct roles for this server. My purpose mey evolve over time. You can always use this command to see my latest features."; - const fields = [ - { - name: "User Commands", - value: - "**/help** - Shows this help embed\n" + - "**/github** - Shows the official GitHub repository for this bot.\n" + - "**/view** - Shows a list of all roles that I have assigned to you\n" + - "**/clear** - Removes all roles that I have assigned to you\n" + - "**/uptime** - Shows how long I have been online\n" + - "**/status** - Shows the status of the bot" - }, - { - name: "Admin Commands", - value: - "**/createRoles** - Creates the roles that will be used in the server and in polls\n" + - "**/staffpoll** - Creates a poll for staff role choosing\n" + - "**/yearpoll** - Creates a poll for year role choosing\n" - }, - { - name: "Features", - value: - "**College Student Roles** - Assigns the correct role for your year in school.\n" + - "**College Employee Roles** - Assigns the correct role for your job title.", - } - ] - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; +export default { + name: "help", + category: "user", + description: "Shows the help embed", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], - const Embed = new MessageEmbed() - .setColor(color) - .setTitle(title) - .setThumbnail(thumbnail) - .setDescription(description) - .addFields(fields) - .setFooter({text: footer, iconURL: footerIcon}); - interaction.reply({embeds: [Embed]}); - - // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/help`)} command in ${chalk.yellow(interaction.guild?.name)}`)); - } - } as ICommand; \ No newline at end of file + callback: async ({ client, interaction }) => { + const color = "#0099ff"; + const thumbnail = + "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; + const title = "Help and Commands List"; + const description = + "Welcome to CSSC-Bot! My purpose in this server is to make sure you have the correct roles for this server. My purpose mey evolve over time. You can always use this command to see my latest features."; + const fields = [ + { + name: "User Commands", + value: + "**/help** - Shows this help embed\n" + + "**/github** - Shows the official GitHub repository for this bot.\n" + + "**/view** - Shows a list of all roles that I have assigned to you\n" + + "**/clear** - Removes all roles that I have assigned to you\n" + + "**/uptime** - Shows how long I have been online\n" + + "**/status** - Shows the status of the bot", + }, + { + name: "Admin Commands", + value: + "**/createRoles** - Creates the roles that will be used in the server and in polls\n" + + "**/staffpoll** - Creates a poll for staff role choosing\n" + + "**/yearpoll** - Creates a poll for year role choosing\n", + }, + { + name: "Features", + value: + "**College Student Roles** - Assigns the correct role for your year in school.\n" + + "**College Employee Roles** - Assigns the correct role for your job title.", + }, + ]; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setThumbnail(thumbnail) + .setDescription(description) + .addFields(fields) + .setFooter({ text: footer, iconURL: footerIcon }); + interaction.reply({ embeds: [Embed] }); + + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/help`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, +} as ICommand; diff --git a/commands/user/ping.ts b/commands/user/ping.ts index 69c2479..672d6b5 100644 --- a/commands/user/ping.ts +++ b/commands/user/ping.ts @@ -3,38 +3,40 @@ import { ICommand } from "wokcommands"; import chalk from "chalk"; export default { - name: "ping", - category: "user", - description: "Sends the ping time of the bot.", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["SEND_MESSAGES"], + name: "ping", + category: "user", + description: "Sends the ping time of the bot.", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], - callback: async ({ client, interaction }) => { - // Embed values - const color = "#0099ff"; - const title = "Bot/API Ping"; - const description = `Ping: 🏓 | Latency is: **${client.ws.ping}**ms.`; - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + callback: async ({ client, interaction }) => { + // Embed values + const color = "#0099ff"; + const title = "Bot/API Ping"; + const description = `Ping: 🏓 | Latency is: **${client.ws.ping}**ms.`; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; - const Embed = new MessageEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter({ text: footer, iconURL: footerIcon }); + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }); - // Return the embed - interaction.reply({ embeds: [Embed] }); + // Return the embed + interaction.reply({ embeds: [Embed] }); - // Log the command usage - console.log( - chalk.blue( - `${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/ping`)} command in ${chalk.yellow( - interaction.guild?.name - )}` - ) - ); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/ping`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/user/status.ts b/commands/user/status.ts index 53d1fef..22742c2 100644 --- a/commands/user/status.ts +++ b/commands/user/status.ts @@ -3,34 +3,44 @@ import { MessageEmbed } from "discord.js"; import { ICommand } from "wokcommands"; export default { - name: "status", - category: "user", - description: "Sends an embed with a link to the status page for the bot.", - slash: true, - testOnly: false, - guildOnly: true, - requiredPermissions: ["SEND_MESSAGES"], + name: "status", + category: "user", + description: "Sends an embed with a link to the status page for the bot.", + slash: true, + testOnly: false, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], - callback: async ({ client, interaction }) => { - // Embed values - const color = "#0099ff"; - const thumbnail = "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; - const title = "Status Page"; - const description = "CLick here to see the bot's status: \nhttps://status.playantares.com"; - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + callback: async ({ client, interaction }) => { + // Embed values + const color = "#0099ff"; + const thumbnail = + "https://playantares.com/resources/CSSC-bot/cssc-server-icon.png"; + const title = "Status Page"; + const description = + "CLick here to see the bot's status: \nhttps://status.playantares.com"; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; - // Embed construction - const Embed = new MessageEmbed() - .setColor(color) - .setTitle(title) - .setThumbnail(thumbnail) - .setDescription(description) - .setFooter({ text: footer, iconURL: footerIcon }); + // Embed construction + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setThumbnail(thumbnail) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }); - interaction.reply({ embeds: [Embed] }); + interaction.reply({ embeds: [Embed] }); - // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/status`)} command in ${chalk.yellow(interaction.guild?.name)}`)); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/status`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/user/uptime.ts b/commands/user/uptime.ts index 4f248cf..c2688cc 100644 --- a/commands/user/uptime.ts +++ b/commands/user/uptime.ts @@ -24,23 +24,31 @@ export default { const seconds = Math.floor(time / 1000) % 60; // Embed values - const color = "#0099ff" - const title = "Bot Uptime" - const description = `I have been online for ${days}d ${hours}h ${minutes}m ${seconds}s` + const color = "#0099ff"; + const title = "Bot Uptime"; + const description = `I have been online for ${days}d ${hours}h ${minutes}m ${seconds}s`; const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; - + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + // Embed construction const Embed = new MessageEmbed() .setColor(color) .setTitle(title) .setDescription(description) - .setFooter({text: footer, iconURL: footerIcon}); - + .setFooter({ text: footer, iconURL: footerIcon }); + // Return the embed - interaction.reply({embeds: [Embed]}); + interaction.reply({ embeds: [Embed] }); // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/uptime`)} command in ${chalk.yellow(interaction.guild?.name)}`)); + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/uptime`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); }, -} as ICommand; \ No newline at end of file +} as ICommand; diff --git a/commands/user/version.ts b/commands/user/version.ts index f6f833b..5a5d42f 100644 --- a/commands/user/version.ts +++ b/commands/user/version.ts @@ -3,38 +3,40 @@ import { ICommand } from "wokcommands"; import chalk from "chalk"; export default { - name: "version", - category: "user", - description: "Sends the version number of the bot", - slash: true, - guildOnly: true, - requiredPermissions: ["SEND_MESSAGES"], + name: "version", + category: "user", + description: "Sends the version number of the bot", + slash: true, + guildOnly: true, + requiredPermissions: ["SEND_MESSAGES"], - callback: async ({ client, interaction }) => { - // Embed values - const color = "#0099ff"; - const title = "Bot Version"; - const description = `I am running version: ${process.env.VERSION}`; - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + callback: async ({ client, interaction }) => { + // Embed values + const color = "#0099ff"; + const title = "Bot Version"; + const description = `I am running version: ${process.env.VERSION}`; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; - // Embed construction - const Embed = new MessageEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter({ text: footer, iconURL: footerIcon }); + // Embed construction + const Embed = new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }); - // Return the embed - interaction.reply({ embeds: [Embed] }); + // Return the embed + interaction.reply({ embeds: [Embed] }); - // Log the command usage - console.log( - chalk.blue( - `${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/version`)} command in ${chalk.yellow( - interaction.guild?.name - )}` - ) - ); - }, + // Log the command usage + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/version`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); + }, } as ICommand; diff --git a/commands/user/view.ts b/commands/user/view.ts index 59cc020..c6b0cd9 100644 --- a/commands/user/view.ts +++ b/commands/user/view.ts @@ -3,7 +3,6 @@ import { GuildMember } from "discord.js"; import { ICommand } from "wokcommands"; import { getUsersRoles } from "../../rolesOps"; - export default { name: "view", category: "user", @@ -14,20 +13,32 @@ export default { requiredPermissions: ["SEND_MESSAGES"], callback: async ({ interaction }) => { - // Remove roles from user if (!interaction.member) return; const list = await getUsersRoles(interaction.member as GuildMember); - // Reply to the user if (list === "") { - interaction.reply({content: "You don't have any College roles assigned to you.", ephemeral: true}); + interaction.reply({ + content: "You don't have any College roles assigned to you.", + ephemeral: true, + }); } else { - interaction.reply({content: "**Your roles:**\n" + list, ephemeral: true}); + interaction.reply({ + content: "**Your roles:**\n" + list, + ephemeral: true, + }); } // Log the command usage - console.log(chalk.blue(`${chalk.green(`[COMMAND]`)} ${chalk.yellow(interaction.user.tag)} used the ${chalk.green(`/view`)} command in ${chalk.yellow(interaction.guild?.name)}`)); + console.log( + chalk.blue( + `${chalk.green(`[COMMAND]`)} ${chalk.yellow( + interaction.user.tag + )} used the ${chalk.green(`/view`)} command in ${chalk.yellow( + interaction.guild?.name + )}` + ) + ); }, -} as ICommand; \ No newline at end of file +} as ICommand; diff --git a/features/interactionCreate.ts b/features/interactionCreate.ts index efe6fdf..2956a80 100644 --- a/features/interactionCreate.ts +++ b/features/interactionCreate.ts @@ -3,86 +3,86 @@ import { removeRole, addNewRole } from "../rolesOps"; // Listen interactionCreate events from the client export default (client: Client): void => { - client.on("interactionCreate", async (interaction) => { - // Make sure the interaction is from a select menu - if (!interaction.isSelectMenu()) return; - const color = "#0099ff"; - const description = `You selected the ${interaction.values[0]} role.`; - const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; - const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; - // Constants for all interactions - const member = interaction.member as GuildMember; + client.on("interactionCreate", async (interaction) => { + // Make sure the interaction is from a select menu + if (!interaction.isSelectMenu()) return; + const color = "#0099ff"; + const description = `You selected the ${interaction.values[0]} role.`; + const footer = `Delivered in: ${client.ws.ping}ms | CSSC-bot | ${process.env.VERSION}`; + const footerIcon = "https://playantares.com/resources/CSSC-bot/icon.jpg"; + // Constants for all interactions + const member = interaction.member as GuildMember; - // Get the select menu by it's custom ID - if (interaction.customId === "collegeYearPoll") { - // Set the embed values - const title = "College Year Poll"; + // Get the select menu by it's custom ID + if (interaction.customId === "collegeYearPoll") { + // Set the embed values + const title = "College Year Poll"; - // Create and send the embed object - interaction.reply({ - embeds: [ - new MessageEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter({ text: footer, iconURL: footerIcon }), - ], - ephemeral: true, - }); - // Remove any previous roles in the dictionary from the user - if (interaction.values[0] === "None") { - removeRole(member, "year"); - return; - } - removeRole(member, "year"); + // Create and send the embed object + interaction.reply({ + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }), + ], + ephemeral: true, + }); + // Remove any previous roles in the dictionary from the user + if (interaction.values[0] === "None") { + removeRole(member, "year"); + return; + } + removeRole(member, "year"); - // Assign the new role to the user - addNewRole(member, "year", interaction.values[0]); - } else if (interaction.customId === "collegeStaffPoll") { - // Set the embed title - const title = "College Staff Poll"; - // Create and send the embed object - interaction.reply({ - embeds: [ - new MessageEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter({ text: footer, iconURL: footerIcon }), - ], - ephemeral: true, - }); - // Remove any previous roles in the dictionary from the user - if (interaction.values[0] === "None") { - removeRole(member, "staff"); - return; - } - removeRole(member, "staff"); + // Assign the new role to the user + addNewRole(member, "year", interaction.values[0]); + } else if (interaction.customId === "collegeStaffPoll") { + // Set the embed title + const title = "College Staff Poll"; + // Create and send the embed object + interaction.reply({ + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }), + ], + ephemeral: true, + }); + // Remove any previous roles in the dictionary from the user + if (interaction.values[0] === "None") { + removeRole(member, "staff"); + return; + } + removeRole(member, "staff"); - // Assign the new role to the user - addNewRole(member, "staff", interaction.values[0]); - } else if (interaction.customId.startsWith("csClassPoll+")) { - // Set the embed title - const title = "CS Class Poll"; - // Create and send the embed object - interaction.reply({ - embeds: [ - new MessageEmbed() - .setColor(color) - .setTitle(title) - .setDescription(description) - .setFooter({ text: footer, iconURL: footerIcon }), - ], - ephemeral: true, - }); - // Assign the new role to the user + // Assign the new role to the user + addNewRole(member, "staff", interaction.values[0]); + } else if (interaction.customId.startsWith("csClassPoll+")) { + // Set the embed title + const title = "CS Class Poll"; + // Create and send the embed object + interaction.reply({ + embeds: [ + new MessageEmbed() + .setColor(color) + .setTitle(title) + .setDescription(description) + .setFooter({ text: footer, iconURL: footerIcon }), + ], + ephemeral: true, + }); + // Assign the new role to the user - addNewRole(member, "class", interaction.values[0]); - } - }); + addNewRole(member, "class", interaction.values[0]); + } + }); }; export const config = { - dbName: "INTERACTION_CREATE", - displayName: "Interaction Create Event (ICE)", + dbName: "INTERACTION_CREATE", + displayName: "Interaction Create Event (ICE)", }; diff --git a/features/status-changer.ts b/features/status-changer.ts index 0d0cd9f..c232230 100644 --- a/features/status-changer.ts +++ b/features/status-changer.ts @@ -1,42 +1,39 @@ import { Client } from "discord.js"; - export default async (client: Client) => { - - const statusOptions = [ - `/help | Ping: ${client.ws.ping}ms`, - `V.${process.env.VERSION}`, - `status.playantares.com`, - `playantares.com/github`, - `status.playantares.com`, - `Antares Network Server Hosting`, - 'Go to #roles!', - 'Hello! I\'m CSSC-Bot', - -]; - let counter = 0; - - const updateStatus = () => { - client.user?.setPresence({ - status: "online", - activities: [ - { - name: statusOptions[counter], - type: "PLAYING", - }, - ], - }); - - if (++counter >= statusOptions.length) { - counter = 0; - } - - setTimeout(updateStatus, 1000 * 60 * 5); - }; - updateStatus(); + const statusOptions = [ + `/help | Ping: ${client.ws.ping}ms`, + `V.${process.env.VERSION}`, + `status.playantares.com`, + `playantares.com/github`, + `status.playantares.com`, + `Antares Network Server Hosting`, + "Go to #roles!", + "Hello! I'm CSSC-Bot", + ]; + let counter = 0; + + const updateStatus = () => { + client.user?.setPresence({ + status: "online", + activities: [ + { + name: statusOptions[counter], + type: "PLAYING", + }, + ], + }); + + if (++counter >= statusOptions.length) { + counter = 0; + } + + setTimeout(updateStatus, 1000 * 60 * 5); + }; + updateStatus(); }; export const config = { - dbName: "STATUS_CHANGER", - displayName: "Status Changer", -}; \ No newline at end of file + dbName: "STATUS_CHANGER", + displayName: "Status Changer", +}; diff --git a/features/statuspage.ts b/features/statuspage.ts index fc4b6bc..2c09c0d 100644 --- a/features/statuspage.ts +++ b/features/statuspage.ts @@ -1,18 +1,18 @@ - import axios from "axios"; import { Client } from "discord.js"; -export default (client: Client): void => { - const updateStatus = async () => { - // This function is called every 1 minutes and pings the network status page for uptime monitoring - axios.get(`https://${process.env.UPTIME_KUMA_MONITOR_DOMAIN}/api/push/${process.env.UPTIME_KUMA_MONITOR_ID}?msg=OK&ping=${client.ws.ping}`); - setTimeout(updateStatus, 1000 * 60); - }; - updateStatus() - .catch(err => console.log(err)); +export default (client: Client): void => { + const updateStatus = async () => { + // This function is called every 1 minutes and pings the network status page for uptime monitoring + axios.get( + `https://${process.env.UPTIME_KUMA_MONITOR_DOMAIN}/api/push/${process.env.UPTIME_KUMA_MONITOR_ID}?msg=OK&ping=${client.ws.ping}` + ); + setTimeout(updateStatus, 1000 * 60); + }; + updateStatus().catch((err) => console.log(err)); }; export const config = { - dbName: "STATUSPAGE_UPDATE", - displayName: "Status Page Update", -}; \ No newline at end of file + dbName: "STATUSPAGE_UPDATE", + displayName: "Status Page Update", +}; diff --git a/index.ts b/index.ts index 05be61e..3bea332 100644 --- a/index.ts +++ b/index.ts @@ -13,60 +13,73 @@ dotenv.config(); // Create a new Discord client const client = new DiscordJs.Client({ - intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS], + intents: [ + Intents.FLAGS.GUILDS, + Intents.FLAGS.GUILD_MESSAGES, + Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, + Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS, + ], }); client.on("ready", () => { - if (client.user) { - console.log(chalk.green(`Logged in as ${client.user.tag}!`)); - console.log(chalk.yellow.bold(`I am running version: ${process.env.VERSION}`)); - // Check to make sure the roles exist in all servers - console.log("Checking if all roles exist in servers.") - client.guilds.cache.forEach(async (guild) => { - checkForRoles(guild); - }); - } + if (client.user) { + console.log(chalk.green(`Logged in as ${client.user.tag}!`)); + console.log( + chalk.yellow.bold(`I am running version: ${process.env.VERSION}`) + ); + // Check to make sure the roles exist in all servers + console.log("Checking if all roles exist in servers."); + client.guilds.cache.forEach(async (guild) => { + checkForRoles(guild); + }); + } - const dbOptions = { - // These are the default values - keepAlive: true, - useNewUrlParser: true, - useUnifiedTopology: true, - }; + const dbOptions = { + // These are the default values + keepAlive: true, + useNewUrlParser: true, + useUnifiedTopology: true, + }; - // Set up the WOKCommands instance - const wok = new WOKCommands(client, { - commandDir: path.join(__dirname, "commands"), - featureDir: path.join(__dirname, "features"), - dbOptions, - typeScript: true, - mongoUri: String(process.env.MONGODB_URI), - disabledDefaultCommands: ["help", "language"], - botOwners: ["603629606154666024", "680813135556378634", "451761128704573440"], - }).setDefaultPrefix(String(process.env.BOT_DEFAULT_PREFIX)); + // Set up the WOKCommands instance + const wok = new WOKCommands(client, { + commandDir: path.join(__dirname, "commands"), + featureDir: path.join(__dirname, "features"), + dbOptions, + typeScript: true, + mongoUri: String(process.env.MONGODB_URI), + disabledDefaultCommands: ["help", "language"], + botOwners: [ + "603629606154666024", + "680813135556378634", + "451761128704573440", + ], + }).setDefaultPrefix(String(process.env.BOT_DEFAULT_PREFIX)); - // Set up the connection to the database - wok.on("databaseConnected", async () => { - console.log(chalk.green("Connected to the database")); - }); + // Set up the connection to the database + wok.on("databaseConnected", async () => { + console.log(chalk.green("Connected to the database")); + }); }); // Catch all errors that are not handled well and just dump to the console. THis will be changed later but for now it's fine. client.on("error", console.error); client.on("warn", (e) => console.warn(e)); process.on("unhandledRejection", (promise, reason) => { - console.error("Unhandled promise rejection:", promise, "\nreason", reason); + console.error("Unhandled promise rejection:", promise, "\nreason", reason); }); // Login to Discord with the bot token and display an error if it fails. client.login(process.env.BOT_TOKEN).catch((error) => { - console.log(chalk.red.bold(`There was an error connecting to the Discord API`)); - console.error(error); - process.exit(1); + console.log( + chalk.red.bold(`There was an error connecting to the Discord API`) + ); + console.error(error); + process.exit(1); }); // Exit gracefully and print the exit code. process.on("exit", (code) => { - console.log("Now exiting..."); - console.log(`Exited with status code: ${code}`); -}); \ No newline at end of file + console.log("Now exiting..."); + console.log(`Exited with status code: ${code}`); +}); diff --git a/models/classModel.ts b/models/classModel.ts index fbcf549..6413cb9 100644 --- a/models/classModel.ts +++ b/models/classModel.ts @@ -2,16 +2,16 @@ import mongoose, { Schema } from "mongoose"; const CLASS = new Schema({ id: String, - CODE: String, - TITLE: String, - INFO: String, - ROLE_NAME: String, - ROLE_ID: String, - CHANNEL_NAME: String, - CHANNEL_ID: String, - UUID: String + CODE: String, + TITLE: String, + INFO: String, + ROLE_NAME: String, + ROLE_ID: String, + CHANNEL_NAME: String, + CHANNEL_ID: String, + UUID: String, }); const name = "class"; -export = mongoose.models[name] || mongoose.model(name, CLASS, name); \ No newline at end of file +export = mongoose.models[name] || mongoose.model(name, CLASS, name); diff --git a/models/staffModel.ts b/models/staffModel.ts index b0b3532..d92ace9 100644 --- a/models/staffModel.ts +++ b/models/staffModel.ts @@ -2,11 +2,11 @@ import mongoose, { Schema } from "mongoose"; const STAFF = new Schema({ id: String, - NAME: String, - ROLE_NAME: String, - ROLE_ID: String, + NAME: String, + ROLE_NAME: String, + ROLE_ID: String, }); const name = "staff"; -export = mongoose.models[name] || mongoose.model(name, STAFF, name); \ No newline at end of file +export = mongoose.models[name] || mongoose.model(name, STAFF, name); diff --git a/models/yearModel.ts b/models/yearModel.ts index 5c7da47..f8bd9f0 100644 --- a/models/yearModel.ts +++ b/models/yearModel.ts @@ -2,12 +2,11 @@ import mongoose, { Schema } from "mongoose"; const YEAR = new Schema({ id: String, - NAME: String, - ROLE_NAME: String, - ROLE_ID: String, - + NAME: String, + ROLE_NAME: String, + ROLE_ID: String, }); const name = "year"; -export = mongoose.models[name] || mongoose.model(name, YEAR, name); \ No newline at end of file +export = mongoose.models[name] || mongoose.model(name, YEAR, name); diff --git a/rolesOps.ts b/rolesOps.ts index d390781..ca6ead1 100644 --- a/rolesOps.ts +++ b/rolesOps.ts @@ -4,111 +4,133 @@ import classModel from "./models/classModel"; import staffModel from "./models/staffModel"; import yearModel from "./models/yearModel"; - -async function dbQuery(){ - const classes = await classModel.find({}); - const staff = await staffModel.find({}); - const years = await yearModel.find({}); - return [classes, staff, years]; +async function dbQuery() { + const classes = await classModel.find({}); + const staff = await staffModel.find({}); + const years = await yearModel.find({}); + return [classes, staff, years]; } export async function getUsersRoles(member: GuildMember): Promise { - let list = ""; - for (const group of await dbQuery()) { - for (const element of group) { - if (member.roles.cache.has(element.ROLE_ID)) { - list += `${member.guild.roles.cache.get(element.ROLE_ID)?.name}\n`; - } - } - } - return list; + let list = ""; + for (const group of await dbQuery()) { + for (const element of group) { + if (member.roles.cache.has(element.ROLE_ID)) { + list += `${member.guild.roles.cache.get(element.ROLE_ID)?.name}\n`; + } + } + } + return list; } -export async function removeRole(member: GuildMember, type: string): Promise { - // This function is triggered when a user changes their role, - // it removes the previous role from the user - let list = []; - if (type === "class") { - list = await classModel.find({}); - } else if (type === "staff") { - list = await staffModel.find({}); - } else if (type === "year") { - list = await yearModel.find({}); - } +export async function removeRole( + member: GuildMember, + type: string +): Promise { + // This function is triggered when a user changes their role, + // it removes the previous role from the user + let list = []; + if (type === "class") { + list = await classModel.find({}); + } else if (type === "staff") { + list = await staffModel.find({}); + } else if (type === "year") { + list = await yearModel.find({}); + } - for (const role of list) { - if (member.roles.cache.has(role.ROLE_ID)) { - await member.roles.remove(role.ROLE_ID); - console.log(chalk.green(`Removed role ${chalk.green(role.ROLE_ID)} from ${chalk.yellow(member.user.tag)}`)); - } - } + for (const role of list) { + if (member.roles.cache.has(role.ROLE_ID)) { + await member.roles.remove(role.ROLE_ID); + console.log( + chalk.green( + `Removed role ${chalk.green(role.ROLE_ID)} from ${chalk.yellow( + member.user.tag + )}` + ) + ); + } + } } -export async function addNewRole(member: GuildMember, type: string, id: string) { - // This function is triggered when a user changes their role, it adds the new role to the user - let role; - if (type === "class") { - role = await classModel.findOne({ CODE: id }); - } else if (type === "staff") { - role = await staffModel.findOne({ NAME: id }); - } else if (type === "year") { - role = await yearModel.findOne({ NAME: id }); - } - if (!member.roles.cache.has(role?.ROLE_ID)) { - await member.roles.add(role?.ROLE_ID); - console.log(chalk.green(`Added role ${chalk.green(role.ROLE_NAME)} to ${chalk.yellow(member.user.tag)}`)); - } +export async function addNewRole( + member: GuildMember, + type: string, + id: string +) { + // This function is triggered when a user changes their role, it adds the new role to the user + let role; + if (type === "class") { + role = await classModel.findOne({ CODE: id }); + } else if (type === "staff") { + role = await staffModel.findOne({ NAME: id }); + } else if (type === "year") { + role = await yearModel.findOne({ NAME: id }); + } + if (!member.roles.cache.has(role?.ROLE_ID)) { + await member.roles.add(role?.ROLE_ID); + console.log( + chalk.green( + `Added role ${chalk.green(role.ROLE_NAME)} to ${chalk.yellow( + member.user.tag + )}` + ) + ); + } } export async function createRoles(guild: Guild, type: string): Promise { - let list; - if (type === "class") { - list = await classModel.find({}); - } else if (type === "staff") { - list = await staffModel.find({}); - } else if (type === "year") { - list = await yearModel.find({}); - } + let list; + if (type === "class") { + list = await classModel.find({}); + } else if (type === "staff") { + list = await staffModel.find({}); + } else if (type === "year") { + list = await yearModel.find({}); + } - list?.forEach(async (element) => { - if (!guild.roles.cache.find((r) => r.name === element.ROLE_NAME)) { - // Create the role - const role = await guild.roles.create({ name: element.ROLE_NAME }); - element.ROLE_ID = role.id; - element.save(); - // Print the role id to the console - console.log(chalk.yellow(`${element}: ${role?.id}`)); - } else { - // If the role already exists, print the id to the console - const role = guild.roles.cache.find((r) => r.name === element.ROLE_NAME); - element.ROLE_ID = role?.id; - element.save(); - console.log(chalk.yellow(`${element}: ${role?.id}`)); - } - }); + list?.forEach(async (element) => { + if (!guild.roles.cache.find((r) => r.name === element.ROLE_NAME)) { + // Create the role + const role = await guild.roles.create({ name: element.ROLE_NAME }); + element.ROLE_ID = role.id; + element.save(); + // Print the role id to the console + console.log(chalk.yellow(`${element}: ${role?.id}`)); + } else { + // If the role already exists, print the id to the console + const role = guild.roles.cache.find((r) => r.name === element.ROLE_NAME); + element.ROLE_ID = role?.id; + element.save(); + console.log(chalk.yellow(`${element}: ${role?.id}`)); + } + }); } export async function checkForRoles(guild: Guild): Promise { - // Check if all roles exist in a guild - // Return true if they do, false if they don't + // Check if all roles exist in a guild + // Return true if they do, false if they don't - let collection: boolean[] = []; + let collection: boolean[] = []; - for (const group of await dbQuery()) { - for (const element of group) { - const name = guild.roles.cache.find((r) => r.name === element.ROLE_NAME); - const id = guild.roles.cache.find((r) => r.id === element.ROLE_ID); + for (const group of await dbQuery()) { + for (const element of group) { + const name = guild.roles.cache.find((r) => r.name === element.ROLE_NAME); + const id = guild.roles.cache.find((r) => r.id === element.ROLE_ID); - if (name == undefined && id == undefined) { - console.log(chalk.red.bold(`Role ${name} does not exist in ${guild.name}, Please run the /createRoles command in that server.`)); - collection.push(false); - } - } - } - if (collection.includes(false)) { - return false; - } else { - console.log(chalk.yellow.bold(`All roles in list exist in ${guild.name}`)); - return true; - } + if (name == undefined && id == undefined) { + console.log( + chalk.red.bold( + `Role ${name} does not exist in ${guild.name}, Please run the /createRoles command in that server.` + ) + ); + collection.push(false); + } + } + } + if (collection.includes(false)) { + return false; + } else { + console.log(chalk.yellow.bold(`All roles in list exist in ${guild.name}`)); + return true; + } } From 9bb583fa90da1b87e086afe6b950aea473a649e1 Mon Sep 17 00:00:00 2001 From: Nate Goldsborough Date: Thu, 1 Sep 2022 13:42:14 -0500 Subject: [PATCH 33/33] Only publish on push to master --- .github/workflows/publish-docker-image.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-docker-image.yml b/.github/workflows/publish-docker-image.yml index 3cd47ad..a52f26e 100644 --- a/.github/workflows/publish-docker-image.yml +++ b/.github/workflows/publish-docker-image.yml @@ -1,5 +1,7 @@ name: Publish Docker image to GitHub Package Registry -on: push +on: + push: + branches: [ "master" ] jobs: build: runs-on: ubuntu-latest