From 81c3f90faa591a12a86a96e6044ac60a5fc61b35 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Wed, 28 Oct 2020 17:57:40 +0100 Subject: [PATCH] Beta Version of Meeting dial in Signed-off-by: Benny Samir Hierl --- Meeting-dial-in/Meeting-dial-in.js | 215 +++++++++++++++++++++++++++++ Meeting-dial-in/README.md | 11 ++ README.md | 5 + Widget-Catalog/catalog.json | 7 + 4 files changed, 238 insertions(+) create mode 100644 Meeting-dial-in/Meeting-dial-in.js create mode 100644 Meeting-dial-in/README.md diff --git a/Meeting-dial-in/Meeting-dial-in.js b/Meeting-dial-in/Meeting-dial-in.js new file mode 100644 index 0000000..da736b8 --- /dev/null +++ b/Meeting-dial-in/Meeting-dial-in.js @@ -0,0 +1,215 @@ +// Variables used by Scriptable. +// These must be at the very top of the file. Do not edit. +// icon-color: light-brown; icon-glyph: magic; +// Version 0.1.0 Beta-Version + +/**************************** +Notice + +Since some services, such as Skype, allow own domains or phone numbers, it cannot be guaranteed that the current search patterns always find all dial-in data. +The search pattern list must be constantly expanded. +If the dial-in data of a meeting should not be recognized, the invitation can be provided under https://github.com/ThisIsBenny/iOS-Widgets/issues/21, so that the list of search patterns can be extended. + +*****************************/ + +let timeformat = 'de-DE' +let countryCode = '+49' + +const listLimit = (config.widgetFamily == 'medium')? 1:5; + +let iconColor; +if (Device.isUsingDarkAppearance()) { + iconColor = 'EDEDED' +} else { + iconColor = '222222' +} + +let now = new Date() +let end = new Date() +end.setHours(23,59,59,999); +const matchPatterns = { + skype: { + online: [ + /Skype-Besprechung teilnehmen <(https?:\/\/[a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF./\-_]*)>/ + ], + phone: [ + {number: /Per Telefon teilnehmen[\r\n\s]+.*/, pin: /Konferenzkennung:[\s]([0-9]+)/} + ] + }, + circuit: { + online: [ + /(https:\/\/eu\.yourcircuit\.com\/guest\?token=[\a-z0-9-]+)/ + ], + phone: [ + {number: /Einwahlnummern[\r\n]*Deutschland[\r\n]*Deutsch[\r\n]*(\+49[0-9\s]+)/, pin: /PIN[\r\n]*([0-9\s]+)#/} + ] + }, + msteams: { + online: [ + /<(https:\/\/teams\.microsoft\.com\/l\/meetup-join\/.+)>/ + ] + } +} + +let upcomingRemoteMeeting = (await CalendarEvent.between(now, end)).map((event) => { + if (event.notes) { + for (const [key, value] of Object.entries(matchPatterns)) { + for (pattern of value.online || []) { + let m = event.notes.match(new RegExp(pattern, 'im')) + if (m && m[1]) { + event.dialInUrl = m[1] + break + } + } + // Some Invitations contains multiple phone numbers with different Country Codes, why first all numbers will be collected and late the needed number with the given country code will be filtered out + let dialInNumbers = [] + for (pattern of value.phone || []) { + let numberMatch = event.notes.match(new RegExp(pattern.number, 'im')) + if (numberMatch && numberMatch[1]) { + let dialInNumber = numberMatch[1] + let pinMatch = event.notes.match(new RegExp(pattern.pin, 'im')) + if (pinMatch && pinMatch[1]) { + dialInNumber += ',,' + pinMatch[1] + '#' + } + dialInNumbers.push(dialInNumber.replace(/%20|[\s\r\n]/g, '')) + } + } + // Find the phonenumber with the given Conuntry Code. + event.dialInNumber = dialInNumbers.find((number) => number.startsWith(countryCode)) + if (event.dialInUrl || event.dialInNumber) { + event.dialInService = key + break + } + } + } + return { + title: event.title, + startDate: event.startDate, + endDate: event.endDate, + dialInService: event.dialInService, + dialInUrl: event.dialInUrl, + dialInNumber: event.dialInNumber + } +}).filter((e) => e.dialInUrl || e.dialInNumber) + +console.log(JSON.stringify(upcomingRemoteMeeting, null, 2)) + +// Create Widget +let widget = new ListWidget(); + +widget.setPadding(10, 10, 10, 10) + +let [nextUpcomingMeeting, ...upComingMeetings] = upcomingRemoteMeeting + +if (config.widgetFamily == 'small') + widget.addText("Small widget isn't supported. Please use the medium or large widget.") + +else if (nextUpcomingMeeting) { + widget.addSpacer(5) + let headlineText = widget.addText("Next Remote Meeting") + headlineText.font = Font.boldSystemFont(12) + + widget.addSpacer(10) + + let stack = widget.addStack() + stack.layoutHorizontally() + + let leftStack = stack.addStack() + leftStack.layoutVertically() + leftStack.size = new Size(260, 70) + + let nextMeetingTime = leftStack.addText(`${(new Date(nextUpcomingMeeting.startDate)).toLocaleString(timeformat)} - ${(new Date(nextUpcomingMeeting.endDate)).toLocaleString(timeformat)}`) + nextMeetingTime.font = Font.thinSystemFont(10) + + let nextMeetingTitle = leftStack.addText(nextUpcomingMeeting.title) + nextMeetingTitle.font = Font.boldSystemFont(20) + nextMeetingTime.minimumScaleFactor = 1 + nextMeetingTime.lineLimit = 2 + + leftStack.addSpacer() + + stack.addSpacer() + + let rightStack = stack.addStack() + rightStack.layoutVertically() + rightStack.size = new Size(25, 70) + + if (nextUpcomingMeeting.dialInNumber) { + let phoneImage = rightStack.addImage(SFSymbol.named('phone').image) + phoneImage.imageSize = new Size(25,25) + phoneImage.url = 'tel:' + nextUpcomingMeeting.dialInNumber + if (iconColor) {phoneImage.tintColor = new Color(iconColor)} + } + + if (nextUpcomingMeeting.dialInUrl) { + rightStack.addSpacer(10) + let videoImage = rightStack.addImage(SFSymbol.named('video').image) + videoImage.imageSize = new Size(25,25) + videoImage.url = nextUpcomingMeeting.dialInUrl + videoImage.centerAlignImage() + if (iconColor) {videoImage.tintColor = new Color(iconColor)} + } + rightStack.addSpacer() + widget.addSpacer() + + let upcomingMeetingStack = widget.addStack() + upcomingMeetingStack.layoutVertically() + + if (upComingMeetings && upComingMeetings.length > 0) { + let upComingText = upcomingMeetingStack.addText((upComingMeetings.length == 1)? 'Upcoming Remote Meeting':'Upcoming Remote Meetings') + upComingText.font = Font.boldSystemFont(10) + upcomingMeetingStack.addSpacer(2) + } + + for (let i = 0; i < listLimit && i < upComingMeetings.length; i++) { + let row = upcomingMeetingStack.addStack() + row.layoutHorizontally() + + let leftColumn = row.addStack() + leftColumn.layoutVertically() + + row.addSpacer() + + let rightColumn = row.addStack() + rightColumn.layoutHorizontally() + rightColumn.setPadding(5, 5, 5, 5) + rightColumn.spacing = 5 + + let meetingTime = leftColumn.addText(`${(new Date(upComingMeetings[i].startDate)).toLocaleString(timeformat)} - ${(new Date(upComingMeetings[i].endDate)).toLocaleString(timeformat)}`) + meetingTime.font = Font.thinSystemFont(8) + + let meetingTitle = leftColumn.addText(upComingMeetings[i].title) + meetingTitle.font = Font.systemFont(10) + meetingTitle.lineLimit = 1 + + if (upComingMeetings[i].dialInNumber) { + let phoneImage = rightColumn.addImage(SFSymbol.named('phone').image) + phoneImage.imageSize = new Size(15,15) + phoneImage.url = 'tel:' + upComingMeetings[i].dialInNumber + if (iconColor) {phoneImage.tintColor = new Color(iconColor)} + } + + if (upComingMeetings[i].dialInUrl) { + let videoImage = rightColumn.addImage(SFSymbol.named('video').image) + videoImage.imageSize = new Size(15,15) + videoImage.url = upComingMeetings[i].dialInUrl + if (iconColor) {videoImage.tintColor = new Color(iconColor)} + } + } + widget.addSpacer(5) +} else { + widget.addSpacer() + let noMeetingText = widget.addText("No upcoming remote meeting") + noMeetingText.font = Font.thinSystemFont(12) + let enjoyText = widget.addText("Enjoy the day") + enjoyText.font = Font.systemFont(20) + widget.addSpacer() +} + +if(!config.runsInWidget) { + await widget.presentLarge() +} else { + // Tell the system to show the widget. + Script.setWidget(widget) + Script.complete() +} diff --git a/Meeting-dial-in/README.md b/Meeting-dial-in/README.md new file mode 100644 index 0000000..5306835 --- /dev/null +++ b/Meeting-dial-in/README.md @@ -0,0 +1,11 @@ +# Meeting dial in (Beta-Version) + +This widget allows you to save the location of your car, which will then displayed in the widget as a map. So you know exactly where you parked. +If you don't know the way to the car anymore, you can start the navigation to the car's location with one click and let Apple Maps or Google Maps navigate you. + +[[Download]](https://raw.githubusercontent.com/ThisIsBenny/iOS-Widgets/main/Meeting-dial-in/Meeting-dial-in.js) + +## Notice +Since some services, such as Skype, allow own domains or phone numbers, it cannot be guaranteed that the current search patterns always find all dial-in data. +The search pattern list must be constantly expanded. +If the dial-in data of a meeting should not be recognized, the invitation can be provided under https://github.com/ThisIsBenny/iOS-Widgets/issues/21, so that the list of search patterns can be extended. \ No newline at end of file diff --git a/README.md b/README.md index 52bd7ec..d7771bd 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,11 @@ You can also download a Script with this Shortcut via iOS Share Menu: https://ww Covid-19 7-Day-Incidence for Düsseldorf + + + + Meeting dial in (Beta-Version) + diff --git a/Widget-Catalog/catalog.json b/Widget-Catalog/catalog.json index 6939776..1c4d892 100644 --- a/Widget-Catalog/catalog.json +++ b/Widget-Catalog/catalog.json @@ -14,6 +14,13 @@ "previewURL": "https://raw.githubusercontent.com/ThisIsBenny/iOS-Widgets/main/Covid-19/previewLight.jpeg", "descriptionURL": "https://github.com/ThisIsBenny/iOS-Widgets/blob/main/Covid-19/README.md" }, + { + "name": "Meeting dial in", + "version": "0.1.0", + "scriptURL": "https://raw.githubusercontent.com/ThisIsBenny/iOS-Widgets/main/Meeting-dial-in/Meeting-dial-in.js", + "previewURL": "", + "descriptionURL": "https://github.com/ThisIsBenny/iOS-Widgets/blob/main/Meeting-dial-in/README.md" + }, { "name": "Vodafone DE remaining data volume", "version": "1.2.1",