Skip to content
This repository has been archived by the owner on Jan 5, 2022. It is now read-only.

Scheduling #5

Open
wants to merge 53 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
725cd6d
Function to get Outlook Calendar Appointments
Blockagle May 11, 2020
cc9aa99
Changed filter method to PS cmdlet vs built in COM object
Blockagle May 11, 2020
f039cfd
Fixed filtering on Outlook items by date
Blockagle May 12, 2020
81f64f4
Added example
Blockagle May 12, 2020
d552fbf
Finds recursive meetings between 2 dates
Blockagle May 12, 2020
46c9c40
Calculates days between 2 days, returns them as datetime objects
Blockagle May 20, 2020
fab6e51
Take strings as input
Blockagle May 20, 2020
578e22b
Returns matched days a meeting occurs on for an array of dates
Blockagle May 20, 2020
a847a4a
Correct variable name
Blockagle May 20, 2020
edc5f2a
Renamed function
Blockagle May 20, 2020
3f404c2
Returns object with Recurring and non recurring appointments
Blockagle May 20, 2020
bc74b6a
Corrected Typo in property match
Blockagle May 20, 2020
5d41688
Fixed typo in Timespan
Blockagle May 20, 2020
a69c990
Calculate the weekly recurring meetings
Blockagle May 20, 2020
f0547a5
Gets recurring meetings separately from standard appts.
Blockagle May 20, 2020
037f198
Removed unused file
Blockagle May 20, 2020
b0e405c
Corrected variable names
Blockagle May 20, 2020
571fd6b
Removed unneeded line
Blockagle May 20, 2020
8b6b45c
Pass dates as strings to private function
Blockagle May 20, 2020
e23cf15
Get Dates for our start dates incase they are strings
Blockagle May 20, 2020
348656f
Return an object that contains appointment objects and dates of the a…
Blockagle May 20, 2020
72779b9
Return an object with an appointment and it's recurrence dates
Blockagle May 20, 2020
2a8a388
Returns object with Time, body and subject
Blockagle May 21, 2020
0762348
Fixes
Blockagle May 21, 2020
4d7d79a
help text
Blockagle May 21, 2020
0b4b719
Help text
Blockagle May 21, 2020
8b4b7be
Comments
Blockagle May 21, 2020
d15e775
Match a zoom URL from a string of text
Blockagle May 21, 2020
34c3ad9
Change " to ' in text string
Blockagle May 21, 2020
65097d2
Correctly exits the process block when the first zoom URL is found
Blockagle May 21, 2020
0c9b550
Moved to public functions
Blockagle May 21, 2020
c4baae2
Rename to proper singular form
Blockagle May 21, 2020
aa64bb4
Increment version and advertise function
Blockagle May 21, 2020
a4ac580
Merge branch 'master' into Scheduling
Blockagle May 21, 2020
a8f4c02
Autoexport functions
Blockagle May 21, 2020
4500d18
Automatic version number, and updated tags
Mortein May 21, 2020
18ce60f
Renamed function to match what it does.
Blockagle May 26, 2020
fabe6dc
Merge branch 'Scheduling' of https://github.com/Mortein/ZoomZoom into…
Blockagle May 26, 2020
fe0c233
Returnt results as they are calulcated
Blockagle May 26, 2020
43cdf37
Added advanced function blocks
Blockagle May 26, 2020
19f61c2
Build objecvt properties when no recurring appts found
Blockagle May 26, 2020
f6bc311
Moved code to process block
Blockagle May 26, 2020
ddab937
Detailed regex in help notes
Blockagle May 26, 2020
2fbd59a
Reworked process to do regex based switch
Blockagle May 27, 2020
0026e2c
Combine regex
Mortein May 29, 2020
d5f28b9
Formatting
Mortein May 29, 2020
901e4f8
Requires at least RemoteSigned to work
Mortein May 29, 2020
5060e82
Force the change
Mortein May 29, 2020
2d1b2c7
Updates notes regarding regex
Mortein May 29, 2020
c6a20ef
Update ZoomZoom/Private/ConvertFrom-AppointmentRecurrencePattern.ps1
Mortein Jun 2, 2020
37a4b87
Update ZoomZoom/Private/Get-DaysInRange.ps1
Mortein Jun 2, 2020
85a0560
Update ZoomZoom/Private/Get-DaysInRange.ps1
Mortein Jun 2, 2020
c13281a
Update ZoomZoom/Private/Get-DaysInRange.ps1
Mortein Jun 2, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions ZoomZoom/Private/Get-DaysInRange.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<#
.SYNOPSIS
Returns the days, months, and years of all days between 2 days
.DESCRIPTION
Calculates a timespan between 2 dates, then returns each day between those 2 dates as datetime objects
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it inclusive or exclusive?

1-3 inclusive returns 1, 2, and 3
1-3 exclusive returns 2

.EXAMPLE
Get-DaysInRange -StartDate 1/1/2020 -EndDate 30/1/2020
Mortein marked this conversation as resolved.
Show resolved Hide resolved
Returns all days in January 2020 as an array
.INPUTS
Datetime strings
.OUTPUTS
Array of Datetime objects
.NOTES

#>

function Get-DaysInRange {
[CmdletBinding()]
param (
# The Start Date for the array to calculate
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]
$StartDate,

# The end date for the array to calculate
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]
$EndDate
)

begin {
$Timespan = New-Timespan -Start $StartDate -End $EndDate
$DateArray = @()
Mortein marked this conversation as resolved.
Show resolved Hide resolved
}

process {
$DateArray += Get-Date $StartDate
Mortein marked this conversation as resolved.
Show resolved Hide resolved
$WorkingTime = Get-Date $StartDate
foreach ($_ in 1..$Timespan.Days) {
$WorkingTime = $WorkingTime.AddDays(1)
Copy link
Owner

@Mortein Mortein May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only returns 2nd day and beyond, never the 1st.

$DateArray += $WorkingTime
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
}
}

end {
return $DateArray
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
}
}
97 changes: 97 additions & 0 deletions ZoomZoom/Private/Get-RecurringMeetingDates.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<#
.SYNOPSIS
Returns an appointment object and all dates for that appointment based off its recurrence pattern
.DESCRIPTION
Takes an Outlook Recurring Appointment object. Calculates all possible occurences of the appointment based off of
the Start timestampt, and the Recurrence Pattern.
The Recurrence Pattern defines a RecurrenceType, an integer that specifies if it's a daily, weekly, monthly, nth monthly,
yearly, or nth yearly meeting.
Each Typoe can then contain DayofWeek masks or WeekofMonth masks that confirm what day, days, or week they occur on.
.EXAMPLE
$Appointment | Get-RecurringMeetingDates -EndDate 30/01/2020
Returns all valid appointment dates for the input recurring appointment object
.INPUTS
Outlook Recurring Appointment
.OUTPUTS
pscustomobject
.NOTES

#>
function Get-RecurringMeetingDates {
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
param (
# An Outlook appointment item
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
[object]
$Appointment,

# The date to calculate the last occurence of a recurring appointment
[Parameter(Mandatory = $false, ValueFromPipeline = $true)]
$EndDate
)

$DateArray = Get-DaysinRange -StartDate ($Appointment.Start).ToString() -EndDate (Get-Date $EndDate).ToString()
$Results = @()

Switch (($Appointment.GetRecurrencePattern()).DayOfWeekMask) {
#CdoMonday/2 - The appointment recurs on Mondays.
2 {
$DayOfWeekMask = $DateArray | Where-Object -Property DayOfWeek -eq 'Monday'
}
#CdoTuesday/4 - The appointment recurs on Tuesdays.
4 {
$DayOfWeekMask = $DateArray | Where-Object -Property DayOfWeek -eq 'Tuesday'
}
#CdoWednesday/8 - The appointment recurs on Wednesdays.
8 {
$DayOfWeekMask = $DateArray | Where-Object -Property DayOfWeek -eq 'Wednesday'
}
#CdoThursday/16 - The appointment recurs on Thursdays.
16 {
$DayOfWeekMask = $DateArray | Where-Object -Property DayOfWeek -eq 'Thursday'
}
#CdoFriday/32 - The appointment recurs on Fridays.
32 {
$DayOfWeekMask = $DateArray | Where-Object -Property DayOfWeek -eq 'Friday'
}
#Meeting that occur on every week day have the value of 62 (2+4+8+16+32)
62 {
$DayOfWeekMask += $DateArray | Where-Object -Property DayOfWeek -NotMatch ^[S*]
}
}

Switch (($Appointment.GetRecurrencePattern()).RecurrenceType) {
#CdoRecurTypeDaily/0 - Appointments that recur daily
0 {
$Results += $DateArray | Where-Object -Property DayOfWeek -NotMatch ^[S*]
return $Results
}
#CdoRecurTypeWeekly/1 - Appointment recurs weekly (DayOfWeekMask,Interval)
1 {
$AppointmentDates = @()
for ($i = 0; $i -lt ($DayOfWeekMask).Count; $i += (($Appointment.GetRecurrencePattern()).Interval)) {
$AppointmentDates += $DayOfWeekMask[$i]
}
$Results += [PSCustomObject]@{
Appointment = $Appointment
AppointmentDates = $AppointmentDates
}
}
#CdoRecurTypeMonthly/2 - Appointment recurs monthly (DayOfMonth Interval)
2 {
#Not yet doing anything with these
}
#CdoRecurTypeMonthlyNth/3 - Appointment recurs every Nth month
3 {
#Not yet doing anything with these
}
#CdoRecurTypeYearly/5 - Appointment recurs every year
5 {
#Not yet doing anything with these
}
#CdoRecurTypeYearlyNth/6 - Appointment recurs every Nth year
6 {
#Not yet doing anything with these
}
}
return $results
}
45 changes: 45 additions & 0 deletions ZoomZoom/Private/Get-ZoomStringFromBody.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<#
.SYNOPSIS
Searches a string for a Zoom Meeting invite URL and returns the first instance found
.DESCRIPTION
Searches a string of text for any Zoom URL's based off the standard Zoom uses. Returns the first line found and splits this incase
there are multiple URLS in 1 line (Common for hyperlink formats)
.INPUTS
String
.OUTPUTS
String
.NOTES
Used to scrape meeting object bodies for Zoom meeting URLs
#>
function Get-ZoomStringFromBody {
[CmdletBinding()]
param (
# A body of text that will contain a Zoom URL
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
$Body
)

begin {
}

process {
$SplitString = $Body -Split ([Environment]::NewLine)
Foreach ($String in $SplitString) {
if ($String -match "\D{5,6}\/\/\S*\/j\/\d{10,11}\?{1}\S*") {
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
$Results = (Select-String -InputObject $String -Pattern "\D{5,6}\/\/\S*\/j\/\d{10,11}\?{1}\S*").Matches.Value
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
break
}
elseif ($String -match "\D{5,6}\/\/\S*\/j\/\d{10,11}") {
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
$results = (Select-String -InputObject $String -Pattern "\D{5,6}\/\/\S*\/j\/\d{10,11}").Matches.Value
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
break
}
else {
$results = $null
}
}
}

end {
return $results
Blockagle marked this conversation as resolved.
Show resolved Hide resolved
}
}
100 changes: 100 additions & 0 deletions ZoomZoom/Public/Get-OutlookCalendarAppointment.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<#
.SYNOPSIS
Returns meeting objects from Outlook
.DESCRIPTION
Creates an Outlook COM application and returns all objects with message class IPM.Appointment from the Calendar Folder from the specified date range. If no date range is specified, all meetings from midnight the previous day, to the current time are returned
.EXAMPLE
Get-OutlookCalendarAppointments
Returns Outlook calendar appointments for the next 48 hours

Get-OutlookCalendarAppointments -Start 12/01/2020 -End 21/02/2020
Returns all non-recurring meetings between 12th January and 21st February 2020

.OUTPUTS
PSCustomObject
.NOTES

#>
function Get-OutlookCalendarAppointment {

[CmdletBinding(DefaultParameterSetName = 'Default')]

param (

# The start date for the search
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'SearchTime')]
$Start,

# The end date for the search
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'SearchTime')]
$End
)

begin {
#Add the required Assembly to PowerShell before processing input
Add-Type -assembly "Microsoft.Office.Interop.Outlook"

#Defines the DefaultFolderID for the Calendar, and creates our new COM Object
$OutlookFolders = 'Microsoft.Office.Interop.Outlook.OlDefaultFolders' -as [type]
$Outlook = New-Object -ComObject Outlook.Application
$NameSpace = $Outlook.GetNamespace('MAPI')

#Empty array to store our results
$Meetings = @()
$Results = @()
if ($PSCmdlet.ParameterSetName -eq 'Default') {
$Start = Get-Date
$End = $Start.AddDays(2)
}
}

process {
$Folder = $NameSpace.getDefaultFolder($OutlookFolders::olFolderCalendar)
$RecurringAppointments = $Folder.Items | Where-Object -Property IsRecurring -eq $True
if ($null -eq $start) {
$Meetings += $Folder.Items | Where-Object -Property Start -gt ((Get-Date -Hour 00 -Minute 00 -Second 00).AddDays(-1))
}
else {
$Meetings += $Folder.Items | Where-Object -Property Start -gt (Get-Date $Start -Hour 00 -Minute 00 -Second 00) | Where-Object -Property End -lt (Get-Date $End -Hour 00 -Minute 00 -Second 00)
}
}

end {
Mortein marked this conversation as resolved.
Show resolved Hide resolved
foreach ($Meeting in $Meetings) {
$Results += [PSCustomObject]@{
MeetingTime = $Meeting.Start
MeetingSubject = $Meeting.Subject
MeetingBody = $Meeting.Body
MeetingURL = Get-ZoomStringFromBody $Meeting.Body
Recurring = $false
}
}
if ($Null -eq $RecurringAppointments) {
return $Results
}
else {
Foreach ($Appointment in $RecurringAppointments) {
$AppointmentDates = @()
$AppointmentDates += (Get-RecurringMeetingDates -Appointment $Appointment -EndDate (Get-Date $End).ToString()).AppointmentDates
foreach ($Date in $AppointmentDates) {
if ($Date -gt (Get-Date $Start)) {
$Results += [pscustomobject]@{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$Results += [pscustomobject]@{
$Result = [pscustomobject]@{

And then grab the section below for the properties of the custom object, add them to $Result, and then output to the pipeline (i.e. remove the return $Results.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we specify the default display set for the properties of the custom object doing it this way?
The fact that the meeting is recurring is not directly important, so hidden using the property set created before results are returned. It is a potentially helpful property to have however

Lines 95-98 for this block in question.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if you take 95-98 and move it to this foreach (inside the if on 83), and then pass to the pipeline after you've set the properties?

Will PowerShell care if you pass an object with default display set, rather than an array of objects with default display set? I have a feeling it'll just merge the objects, as long as the display set is the same.

MeetingTime = $Date
MeetingSubject = $Appointment.Subject
MeetingBody = $Appointment.Body
MeetingURL = Get-ZoomStringFromBody $Appointment.Body
Recurring = $true
}
}
}
}

$defaultProperties = @('MeetingTime', 'MeetingSubject', 'MeetingURL', 'Recurring')
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet(‘DefaultDisplayPropertySet’, [string[]]$defaultProperties)
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
$Results | Add-Member MemberSet PSStandardMembers $PSStandardMembers

return $Results
}
}
}
Binary file modified ZoomZoom/ZoomZoom.psd1
Binary file not shown.