Skip to content

Commit

Permalink
Merge pull request #299 from czqoocavatsim/JoshuaBranch
Browse files Browse the repository at this point in the history
Auto Training Updates (Sunday @ 17z)
  • Loading branch information
JoshuaMicallefYBSU authored Aug 18, 2024
2 parents f86795e + 1520332 commit bc9a3f3
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 22 deletions.
4 changes: 4 additions & 0 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Jobs\ProcessSessionReminders;
use App\Jobs\ProcessSoloCertExpiryWarnings;
use App\Jobs\ProcessShanwickController;
use App\Jobs\DiscordTrainingUpdates;
use App\Models\Roster\RosterMember;
use App\Notifications\Network\OneWeekInactivityReminder;
use App\Notifications\Network\TwoWeekInactivityReminder;
Expand Down Expand Up @@ -104,6 +105,9 @@ protected function schedule(Schedule $schedule)
//Training/OTS session reminders
$schedule->job(new ProcessSessionReminders())->daily();

// Check Training Threads Status (Once per week)
$schedule->job(new DiscordTrainingUpdates())->weeklyOn(7, '17:00');

// Discord role updating
//$schedule->job(new UpdateDiscordUserRoles)->twiceDaily(6, 18);
}
Expand Down
4 changes: 2 additions & 2 deletions app/Http/Controllers/DiscordTestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Illuminate\Http\Request;
use App\Services\DiscordClient;
use App\Jobs\ProcessShanwickController;
use App\Jobs\DiscordTrainingUpdates;

class DiscordTestController extends Controller
{
Expand All @@ -26,7 +26,7 @@ public function EditTagTest()
public function Shanwick()
{
// Dispatch the job
$job = ProcessShanwickController::dispatch();
$job = DiscordTrainingUpdates::dispatch();

// Call the handle method directly to get the result synchronously
$result = $job->handle();
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Training/ApplicationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public function applyPost(Request $request)
$discord = new DiscordClient();
$discord->sendMessageWithEmbed(config('app.env') == 'local' ? intval(config('services.discord.web_logs')) : intval(config('services.discord.applications')), 'New Training Applicant!', $application->user->fullName('FLC').' has just applied to control at Gander Oceanic!
[View their application now](https://ganderoceanic.ca/admin/training/applications/'.$application->reference_id.')');
[View their application now](https://ganderoceanic.ca/admin/training/applications/'.$application->reference_id.')');

//Redirect to application page
return redirect()->route('training.applications.show', $application->reference_id);
Expand Down
33 changes: 21 additions & 12 deletions app/Http/Controllers/Training/InstructingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function instructors()
public function students()
{
//Get all students
$students = Student::whereCurrent(true)->orderBy('created_at', 'desc')->get();
$students = Student::whereCurrent(true)->orderBy('created_at', 'asc')->get();
$pastStudents = Student::whereCurrent(false)->orderBy('updated_at', 'desc')->get();

//Return view
Expand Down Expand Up @@ -600,19 +600,22 @@ public function assignStudentToInstructor(Request $request, $student_id)
$link->student_id = $student->id;
$link->save();

//If student has ready for pick up, remove and add In Progress
//Relabelling process
foreach ($student->labels as $label) {
//Find label
if (strtolower($label->label()->name) == 'ready for pick-up') {
$label->delete();
$label->delete();
}

//Assign it with link
$link = new StudentStatusLabelLink([
'student_id' => $student->id,
'student_status_label_id' => StudentStatusLabel::whereName('In Progress')->first()->id,
]);
$link->save();

//Assign it with link
$link = new StudentStatusLabelLink([
'student_id' => $student->id,
'student_status_label_id' => StudentStatusLabel::whereName('In Progress')->first()->id,
]);
$link->save();
}
// Update Thread Tag
if ($student->user->hasDiscord() && $student->user->member_of_czqo) {
$discord = new DiscordClient();
$discord->EditThreadTag('In Progress', $student->user->id);
}

//Notify instructor
Expand Down Expand Up @@ -646,6 +649,12 @@ public function dropStudentFromInstructor($student_id)
]);
$link->save();

// Update Thread Tag
if ($student->user->hasDiscord() && $student->user->member_of_czqo) {
$discord = new DiscordClient();
$discord->EditThreadTag('Ready For Pick-Up', $student->user->id);
}

//Discord notification in instructors channel
$discord = new DiscordClient();
$discord->sendMessageWithEmbed(intval(config('services.discord.instructors')), 'A new student is available for pick-up by an Instructor', $student->user->fullName('FLC').' is available to be picked up by an instructor!');
Expand Down
231 changes: 231 additions & 0 deletions app/Jobs/DiscordTrainingUpdates.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

use GuzzleHttp\Client;
use App\Services\DiscordClient;
use App\Models\Training\Instructing\Records\TrainingSession;
use App\Models\Training\Instructing\Students\Student;
use App\Notifications\Training\Instructing\RemovedAsStudent;
use App\Models\Training\Instructing\Students\StudentStatusLabel;
use App\Models\Training\Instructing\Links\StudentStatusLabelLink;
use Carbon\Carbon;

class DiscordTrainingUpdates implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// Check all Training Threads are open and dont expire for one week
{
// Initialize the DiscordClient inside the handle method
$discord = new DiscordClient();

// Number of Messages Sent
$counter = 0;

// Get Active Threads
$response = $discord->getClient()->get('channels/'.env('DISCORD_TRAINING_FORUM').'/threads/archived/public');
$results = json_decode($response->getBody(), true);

// dd($results);

foreach($results['threads'] as $thread){
$archiveTimestamp = Carbon::parse($thread['thread_metadata']['archive_timestamp']);

// Thread was closed within the last 10 days
if ($archiveTimestamp >= Carbon::now()->subDays(10) && $archiveTimestamp <= Carbon::now()) {
// Your code to handle the condition
// dd($archiveTimestamp);

// Get the ID of the Training Thread Recently Closed
if (preg_match('/\d+$/', $thread['name'], $matches)) {
$cid = $matches[0];
} else {
$cid = null;
}

// See if CID is still a student
$student = Student::where('user_id', $cid)->first();
if($student !== null){

// Thread should be active, so lets activate it.
$discord = new DiscordClient();
$data = $discord->getClient()->patch('channels/'.$thread['id'], [
'json' => [
'locked' => false,
'archived' => false,
]
]);
}
}
}

$discord->sendMessageWithEmbed(env('DISCORD_WEB_LOGS'), 'AUTO: Training Thread Opened',$counter. ' Threads were automatically reopended as they had expired (more than 1 week since last activity)');
}

// Function for Training Thread Availability Updates
{
// Initialize the DiscordClient inside the handle method
$discord = new DiscordClient();

// Number of Messages Sent
$counter = 0;

// Get Active Threads
$response = $discord->getClient()->get('guilds/'.env('DISCORD_GUILD_ID').'/threads/active');
$results = json_decode($response->getBody(), true);

foreach ($results['threads'] as $thread) {

// Get the ID of the Active Training Thread
if (preg_match('/\d+$/', $thread['name'], $matches)) {
$cid = $matches[0];
} else {
$cid = null;
}

// Check Lable is 'In Progress' or 'Ready For Pick-Up'

// Check Sessions Upcoming
$student = Student::where('user_id', $cid)->first();
$upcoming_sessions = TrainingSession::where('student_id', $student->id)->whereBetween('scheduled_time', [Carbon::now(), Carbon::now()->addDays(7)])->first();

if($upcoming_sessions == null){
// There is no sessions within the next week
$counter++; //Add 1 to the $counter variable

// SendEmbed to ask student to send availability
$discord->sendEmbedInTrainingThread($cid, "Your Availability", 'Hello, <@'.$student->user->discord_user_id.'>
Please provide your availability for the next 7-14 days. Please ensure to tag the `@Instructor` role with all times you are available. Please provide these times in Zulu Format.
One of our team will make contact with you to organise a session if they have availability matching yours.
*If you have done this in the past few days, please disregard this message.*');
}
}

// Tell the log chat
$discord->sendMessageWithEmbed(env('DISCORD_WEB_LOGS'), 'AUTO: Training Thread Availability Requests',$counter. ' Training Threads have been messaged asking for their weekly availability. This is only completed if a student has no scheduled session within the next 7 days.');
}

// Check 'Awaiting Exam' label students between 31-37 Days after Application
{
$count = 0;

$student = Student::whereBetween('created_at', [Carbon::now()->subDays(37), Carbon::now()->subDays(30)])->where('current', true)->get();

foreach($student as $s){
if ($s->hasLabel('Awaiting Exam')) {
// Add one to the count
$count++;
// SendEmbed to ask student to send availability
$discord->sendEmbedInTrainingThread($cid, "Exam Not Requested", 'Hello, <@'.$s->user->discord_user_id.'>
Our records indicate that you have not requested, or completed your exam within a month of your Application being approved.
Please read the above message in order to understand how to request the exam.
Should you not request, and pass the exam within 60 days of your application being accepted, your training will be automatically terminated, and you will need to reapply to begin your training once more.
**Kind Regards,
Gander Oceanic Training Team**');
}
}

// Tell the log chat
$discord->sendMessageWithEmbed(env('DISCORD_WEB_LOGS'), 'AUTO: Training Thread Exam Requests Reminder',$count. ' Students are between 30-37 days past application without completing the exam. They have been notified of this.');
}


// Check 'Awaiting-Exam' label students 60 Days after Application and Terminate Training Automatically
{
$count2 = 0;

$student = Student::where('created_at', '<=', Carbon::now()->subDays(60))->where('current', true)->get();

foreach($student as $s){
if ($s->hasLabel('Awaiting Exam')) {
// Add one to the count
$count2++;

// dd($s);

//Make as not current
$s->current = false;

//Remove role
$s->user->removeRole('Student');

//Discord Updates
if ($s->user->hasDiscord() && $s->user->member_of_czqo) {
//Get Discord client
$discord = new DiscordClient();

//remove student discord role
$discord->removeRole($s->user->discord_user_id, 482824058141016075);

$discord->EditThreadTag('Inactive', $s->user->id);

//close training Thread
$discord->closeTrainingThread($s->user->id, $s->user->discord_user_id, 'terminate');

// Notify Senior Team that new training has been terminated.
$discord->sendMessageWithEmbed(config('app.env') == 'local' ? intval(config('services.discord.web_logs')) : intval(config('services.discord.instructors')), 'Training Terminated', $s->user->fullName('FLC').' has had their training terminated. `Exam not completed within 60 days.`', 'error');

} else {
//Get Discord client
$discord = new DiscordClient();

// Notify Senior Team that training has been terminated
$discord->sendMessageWithEmbed(config('app.env') == 'local' ? intval(config('services.discord.web_logs')) : intval(config('services.discord.instructors')), 'Training Terminated', $s->user->fullName('FLC').' has had their training terminated. `Exam not completed within 60 days.`', 'error');
}

foreach ($s->labels as $label) {
if (!in_array($label->label()->name, ['inactive'])) {
$label->delete();
}
}

//Remove labels and instructor links and availability
$label = new StudentStatusLabelLink([
'student_status_label_id' => StudentStatusLabel::whereName('Inactive')->first()->id,
'student_id' => $s->id,
]);
$label->save();


if ($s->instructor()) {
$s->instructor()->delete();
}
foreach ($s->availability as $a) {
$a->delete();
}

//notify
$s->user->notify(new RemovedAsStudent());

//Save
$s->save();
}
}

// Tell the log chat
$discord->sendMessageWithEmbed(env('DISCORD_WEB_LOGS'), 'AUTO: Training Termination',$count2. ' Students have been terminated automatically. Exam not completed within 60 days.');

}
}
}
32 changes: 28 additions & 4 deletions app/Services/DiscordClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public function __construct()
]);
}

// Get Discord Client (For external use outside of this php file)
public function getClient() {
return $this->client;
}

public function sendMessage($channelId, $message)
{
$response = $this->client->post("channels/{$channelId}/messages", [
Expand Down Expand Up @@ -91,6 +96,7 @@ public function createTrainingThread($name, $user)
$response = $this->client->post("channels/".env('DISCORD_TRAINING_FORUM')."/threads", [
'json' => [
'name' => $name,
'auto_archive_duration' => 20160,
'applied_tags' => [1271845980865695774], //Tag ID for 'New Request'
'message' => [
'content' => $user.', your application has now been approved. Welcome to Gander Oceanic!
Expand Down Expand Up @@ -132,16 +138,34 @@ public function closeTrainingThread($cid, $discord_id, $status)
$this->sendMessageWithEmbed($thread['id'], 'Oceanic Training Completed!',
'Congratulations <@'.$discord_id.'>, you have now been certified on Gander & Shanwick Oceanic!
This training thread will now be closed due to the completion of your training. Your discord roles will automatically be updated within the next 24 Hours.
This training thread will now be closed due to the completion of your training. Your discord roles will automatically be updated within the next 24
If you have any questions, please reach out to your Instructor, or ask your question in <#836707337829089322>.
Enjoy controlling Gander & Shanwick OCA!');
Enjoy controlling Gander & Shanwick OCA!
**Kind Regards,
Gander Oceanic Training Team**');

} elseif($status == "cancel") {
$this->sendMessageWithEmbed($thread['id'], 'Oceanic Training Cancelled',
'<@'.$discord_id.'>, Your training request with Gander Oceanic has been terminated on <t:'.Carbon::now()->timestamp.':F>
'<@'.$discord_id.'>, Your training request with Gander Oceanic has been terminated at <t:'.Carbon::now()->timestamp.':F>
If you would like to begin training again, please re-apply via the Gander Website.
**Kind Regards,
Gander Oceanic Training Team**');

} elseif($status == "terminate"){
$this->sendMessageWithEmbed($thread['id'], 'Oceanic Training Terminated',
'<@'.$discord_id.'>, Your training request with Gander Oceanic has been terminated at <t:'.Carbon::now()->timestamp.':F>.
This is due to not completing the Exam within 60 Days of your application being accepted.
If you would like to begin training again, please re-apply via the Gander Website.
If you would like to begin training again, please re-apply via the Gander Website.');
**Kind Regards,
Gander Oceanic Training Team**');
}

// Lock and Archive the Thread
Expand Down
Loading

0 comments on commit bc9a3f3

Please sign in to comment.