flowtask 5.8.4__cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flowtask/__init__.py +93 -0
- flowtask/__main__.py +38 -0
- flowtask/bots/__init__.py +6 -0
- flowtask/bots/check.py +93 -0
- flowtask/bots/codebot.py +51 -0
- flowtask/components/ASPX.py +148 -0
- flowtask/components/AddDataset.py +352 -0
- flowtask/components/Amazon.py +523 -0
- flowtask/components/AutoTask.py +314 -0
- flowtask/components/Azure.py +80 -0
- flowtask/components/AzureUsers.py +106 -0
- flowtask/components/BaseAction.py +91 -0
- flowtask/components/BaseLoop.py +198 -0
- flowtask/components/BestBuy.py +800 -0
- flowtask/components/CSVToGCS.py +120 -0
- flowtask/components/CompanyScraper/__init__.py +1 -0
- flowtask/components/CompanyScraper/parsers/__init__.py +6 -0
- flowtask/components/CompanyScraper/parsers/base.py +102 -0
- flowtask/components/CompanyScraper/parsers/explorium.py +192 -0
- flowtask/components/CompanyScraper/parsers/leadiq.py +206 -0
- flowtask/components/CompanyScraper/parsers/rocket.py +133 -0
- flowtask/components/CompanyScraper/parsers/siccode.py +109 -0
- flowtask/components/CompanyScraper/parsers/visualvisitor.py +130 -0
- flowtask/components/CompanyScraper/parsers/zoominfo.py +118 -0
- flowtask/components/CompanyScraper/scrapper.py +1054 -0
- flowtask/components/CopyTo.py +177 -0
- flowtask/components/CopyToBigQuery.py +243 -0
- flowtask/components/CopyToMongoDB.py +291 -0
- flowtask/components/CopyToPg.py +609 -0
- flowtask/components/CopyToRethink.py +207 -0
- flowtask/components/CreateGCSBucket.py +102 -0
- flowtask/components/CreateReport/CreateReport.py +228 -0
- flowtask/components/CreateReport/__init__.py +9 -0
- flowtask/components/CreateReport/charts/__init__.py +15 -0
- flowtask/components/CreateReport/charts/bar.py +51 -0
- flowtask/components/CreateReport/charts/base.py +66 -0
- flowtask/components/CreateReport/charts/pie.py +64 -0
- flowtask/components/CreateReport/utils.py +9 -0
- flowtask/components/CustomerSatisfaction.py +196 -0
- flowtask/components/DataInput.py +200 -0
- flowtask/components/DateList.py +255 -0
- flowtask/components/DbClient.py +163 -0
- flowtask/components/DialPad.py +146 -0
- flowtask/components/DocumentDBQuery.py +200 -0
- flowtask/components/DownloadFrom.py +371 -0
- flowtask/components/DownloadFromD2L.py +113 -0
- flowtask/components/DownloadFromFTP.py +181 -0
- flowtask/components/DownloadFromIMAP.py +315 -0
- flowtask/components/DownloadFromS3.py +198 -0
- flowtask/components/DownloadFromSFTP.py +265 -0
- flowtask/components/DownloadFromSharepoint.py +110 -0
- flowtask/components/DownloadFromSmartSheet.py +114 -0
- flowtask/components/DownloadS3File.py +229 -0
- flowtask/components/Dummy.py +59 -0
- flowtask/components/DuplicatePhoto.py +411 -0
- flowtask/components/EmployeeEvaluation.py +237 -0
- flowtask/components/ExecuteSQL.py +323 -0
- flowtask/components/ExtractHTML.py +178 -0
- flowtask/components/FileBase.py +178 -0
- flowtask/components/FileCopy.py +181 -0
- flowtask/components/FileDelete.py +82 -0
- flowtask/components/FileExists.py +146 -0
- flowtask/components/FileIteratorDelete.py +112 -0
- flowtask/components/FileList.py +194 -0
- flowtask/components/FileOpen.py +75 -0
- flowtask/components/FileRead.py +120 -0
- flowtask/components/FileRename.py +106 -0
- flowtask/components/FilterIf.py +284 -0
- flowtask/components/FilterRows/FilterRows.py +200 -0
- flowtask/components/FilterRows/__init__.py +10 -0
- flowtask/components/FilterRows/functions.py +4 -0
- flowtask/components/GCSToBigQuery.py +103 -0
- flowtask/components/GoogleA4.py +150 -0
- flowtask/components/GoogleGeoCoding.py +344 -0
- flowtask/components/GooglePlaces.py +315 -0
- flowtask/components/GoogleSearch.py +539 -0
- flowtask/components/HTTPClient.py +268 -0
- flowtask/components/ICIMS.py +146 -0
- flowtask/components/IF.py +179 -0
- flowtask/components/IcimsFolderCopy.py +173 -0
- flowtask/components/ImageFeatures/__init__.py +5 -0
- flowtask/components/ImageFeatures/process.py +233 -0
- flowtask/components/IteratorBase.py +251 -0
- flowtask/components/LangchainLoader/__init__.py +5 -0
- flowtask/components/LangchainLoader/loader.py +194 -0
- flowtask/components/LangchainLoader/loaders/__init__.py +22 -0
- flowtask/components/LangchainLoader/loaders/abstract.py +362 -0
- flowtask/components/LangchainLoader/loaders/basepdf.py +50 -0
- flowtask/components/LangchainLoader/loaders/docx.py +91 -0
- flowtask/components/LangchainLoader/loaders/html.py +119 -0
- flowtask/components/LangchainLoader/loaders/pdfblocks.py +146 -0
- flowtask/components/LangchainLoader/loaders/pdfmark.py +79 -0
- flowtask/components/LangchainLoader/loaders/pdftables.py +135 -0
- flowtask/components/LangchainLoader/loaders/qa.py +67 -0
- flowtask/components/LangchainLoader/loaders/txt.py +55 -0
- flowtask/components/LeadIQ.py +650 -0
- flowtask/components/Loop.py +253 -0
- flowtask/components/Lowes.py +334 -0
- flowtask/components/MS365Usage.py +156 -0
- flowtask/components/MSTeamsMessages.py +320 -0
- flowtask/components/MarketClustering.py +1051 -0
- flowtask/components/MergeFiles.py +362 -0
- flowtask/components/MilvusOutput.py +87 -0
- flowtask/components/NearByStores.py +175 -0
- flowtask/components/NetworkNinja/__init__.py +6 -0
- flowtask/components/NetworkNinja/models/__init__.py +52 -0
- flowtask/components/NetworkNinja/models/abstract.py +177 -0
- flowtask/components/NetworkNinja/models/account.py +39 -0
- flowtask/components/NetworkNinja/models/client.py +19 -0
- flowtask/components/NetworkNinja/models/district.py +14 -0
- flowtask/components/NetworkNinja/models/events.py +101 -0
- flowtask/components/NetworkNinja/models/forms.py +499 -0
- flowtask/components/NetworkNinja/models/market.py +16 -0
- flowtask/components/NetworkNinja/models/organization.py +34 -0
- flowtask/components/NetworkNinja/models/photos.py +125 -0
- flowtask/components/NetworkNinja/models/project.py +44 -0
- flowtask/components/NetworkNinja/models/region.py +28 -0
- flowtask/components/NetworkNinja/models/store.py +203 -0
- flowtask/components/NetworkNinja/models/user.py +151 -0
- flowtask/components/NetworkNinja/router.py +854 -0
- flowtask/components/Odoo.py +175 -0
- flowtask/components/OdooInjector.py +192 -0
- flowtask/components/OpenFromXML.py +126 -0
- flowtask/components/OpenWeather.py +41 -0
- flowtask/components/OpenWithBase.py +616 -0
- flowtask/components/OpenWithPandas.py +715 -0
- flowtask/components/PGPDecrypt.py +199 -0
- flowtask/components/PandasIterator.py +187 -0
- flowtask/components/PandasToFile.py +189 -0
- flowtask/components/Paradox.py +339 -0
- flowtask/components/ParamIterator.py +117 -0
- flowtask/components/ParseHTML.py +84 -0
- flowtask/components/PlacerStores.py +249 -0
- flowtask/components/Pokemon.py +507 -0
- flowtask/components/PositiveBot.py +62 -0
- flowtask/components/PowerPointSlide.py +400 -0
- flowtask/components/PrintMessage.py +127 -0
- flowtask/components/ProductCompetitors/__init__.py +5 -0
- flowtask/components/ProductCompetitors/parsers/__init__.py +7 -0
- flowtask/components/ProductCompetitors/parsers/base.py +72 -0
- flowtask/components/ProductCompetitors/parsers/bestbuy.py +86 -0
- flowtask/components/ProductCompetitors/parsers/lowes.py +103 -0
- flowtask/components/ProductCompetitors/scrapper.py +155 -0
- flowtask/components/ProductCompliant.py +169 -0
- flowtask/components/ProductInfo/__init__.py +1 -0
- flowtask/components/ProductInfo/parsers/__init__.py +5 -0
- flowtask/components/ProductInfo/parsers/base.py +83 -0
- flowtask/components/ProductInfo/parsers/brother.py +97 -0
- flowtask/components/ProductInfo/parsers/canon.py +167 -0
- flowtask/components/ProductInfo/parsers/epson.py +118 -0
- flowtask/components/ProductInfo/parsers/hp.py +131 -0
- flowtask/components/ProductInfo/parsers/samsung.py +97 -0
- flowtask/components/ProductInfo/scraper.py +319 -0
- flowtask/components/ProductPricing.py +118 -0
- flowtask/components/QS.py +261 -0
- flowtask/components/QSBase.py +201 -0
- flowtask/components/QueryIterator.py +273 -0
- flowtask/components/QueryToInsert.py +327 -0
- flowtask/components/QueryToPandas.py +432 -0
- flowtask/components/RESTClient.py +195 -0
- flowtask/components/RethinkDBQuery.py +189 -0
- flowtask/components/Rsync.py +74 -0
- flowtask/components/RunSSH.py +59 -0
- flowtask/components/RunShell.py +71 -0
- flowtask/components/SalesForce.py +20 -0
- flowtask/components/SaveImageBank/__init__.py +257 -0
- flowtask/components/SchedulingVisits.py +592 -0
- flowtask/components/ScrapPage.py +216 -0
- flowtask/components/ScrapSearch.py +79 -0
- flowtask/components/SendNotify.py +257 -0
- flowtask/components/SentimentAnalysis.py +694 -0
- flowtask/components/ServiceScrapper/__init__.py +5 -0
- flowtask/components/ServiceScrapper/parsers/__init__.py +1 -0
- flowtask/components/ServiceScrapper/parsers/base.py +94 -0
- flowtask/components/ServiceScrapper/parsers/costco.py +93 -0
- flowtask/components/ServiceScrapper/scrapper.py +199 -0
- flowtask/components/SetVariables.py +156 -0
- flowtask/components/SubTask.py +182 -0
- flowtask/components/SuiteCRM.py +48 -0
- flowtask/components/Switch.py +175 -0
- flowtask/components/TableBase.py +148 -0
- flowtask/components/TableDelete.py +312 -0
- flowtask/components/TableInput.py +143 -0
- flowtask/components/TableOutput/TableOutput.py +384 -0
- flowtask/components/TableOutput/__init__.py +3 -0
- flowtask/components/TableSchema.py +534 -0
- flowtask/components/Target.py +223 -0
- flowtask/components/ThumbnailGenerator.py +156 -0
- flowtask/components/ToPandas.py +67 -0
- flowtask/components/TransformRows/TransformRows.py +507 -0
- flowtask/components/TransformRows/__init__.py +9 -0
- flowtask/components/TransformRows/functions.py +559 -0
- flowtask/components/TransposeRows.py +176 -0
- flowtask/components/UPCDatabase.py +86 -0
- flowtask/components/UnGzip.py +171 -0
- flowtask/components/Uncompress.py +172 -0
- flowtask/components/UniqueRows.py +126 -0
- flowtask/components/Unzip.py +107 -0
- flowtask/components/UpdateOperationalVars.py +147 -0
- flowtask/components/UploadTo.py +299 -0
- flowtask/components/UploadToS3.py +136 -0
- flowtask/components/UploadToSFTP.py +160 -0
- flowtask/components/UploadToSharepoint.py +205 -0
- flowtask/components/UserFunc.py +122 -0
- flowtask/components/VivaTracker.py +140 -0
- flowtask/components/WSDLClient.py +123 -0
- flowtask/components/Wait.py +18 -0
- flowtask/components/Walmart.py +199 -0
- flowtask/components/Workplace.py +134 -0
- flowtask/components/XMLToPandas.py +267 -0
- flowtask/components/Zammad/__init__.py +41 -0
- flowtask/components/Zammad/models.py +0 -0
- flowtask/components/ZoomInfoScraper.py +409 -0
- flowtask/components/__init__.py +104 -0
- flowtask/components/abstract.py +18 -0
- flowtask/components/flow.py +530 -0
- flowtask/components/google.py +335 -0
- flowtask/components/group.py +221 -0
- flowtask/components/py.typed +0 -0
- flowtask/components/reviewscrap.py +132 -0
- flowtask/components/tAutoincrement.py +117 -0
- flowtask/components/tConcat.py +109 -0
- flowtask/components/tExplode.py +119 -0
- flowtask/components/tFilter.py +184 -0
- flowtask/components/tGroup.py +236 -0
- flowtask/components/tJoin.py +270 -0
- flowtask/components/tMap/__init__.py +9 -0
- flowtask/components/tMap/functions.py +54 -0
- flowtask/components/tMap/tMap.py +450 -0
- flowtask/components/tMelt.py +112 -0
- flowtask/components/tMerge.py +114 -0
- flowtask/components/tOrder.py +93 -0
- flowtask/components/tPandas.py +94 -0
- flowtask/components/tPivot.py +71 -0
- flowtask/components/tPluckCols.py +76 -0
- flowtask/components/tUnnest.py +82 -0
- flowtask/components/user.py +401 -0
- flowtask/conf.py +457 -0
- flowtask/download.py +102 -0
- flowtask/events/__init__.py +11 -0
- flowtask/events/events/__init__.py +20 -0
- flowtask/events/events/abstract.py +95 -0
- flowtask/events/events/alerts/__init__.py +362 -0
- flowtask/events/events/alerts/colfunctions.py +131 -0
- flowtask/events/events/alerts/functions.py +158 -0
- flowtask/events/events/dummy.py +12 -0
- flowtask/events/events/exec.py +124 -0
- flowtask/events/events/file/__init__.py +7 -0
- flowtask/events/events/file/base.py +51 -0
- flowtask/events/events/file/copy.py +23 -0
- flowtask/events/events/file/delete.py +16 -0
- flowtask/events/events/interfaces/__init__.py +9 -0
- flowtask/events/events/interfaces/client.py +67 -0
- flowtask/events/events/interfaces/credentials.py +28 -0
- flowtask/events/events/interfaces/notifications.py +58 -0
- flowtask/events/events/jira.py +122 -0
- flowtask/events/events/log.py +26 -0
- flowtask/events/events/logerr.py +52 -0
- flowtask/events/events/notify.py +59 -0
- flowtask/events/events/notify_event.py +160 -0
- flowtask/events/events/publish.py +54 -0
- flowtask/events/events/sendfile.py +104 -0
- flowtask/events/events/task.py +97 -0
- flowtask/events/events/teams.py +98 -0
- flowtask/events/events/webhook.py +58 -0
- flowtask/events/manager.py +287 -0
- flowtask/exceptions.c +39393 -0
- flowtask/exceptions.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/extensions/__init__.py +3 -0
- flowtask/extensions/abstract.py +82 -0
- flowtask/extensions/logging/__init__.py +65 -0
- flowtask/hooks/__init__.py +9 -0
- flowtask/hooks/actions/__init__.py +22 -0
- flowtask/hooks/actions/abstract.py +66 -0
- flowtask/hooks/actions/dummy.py +23 -0
- flowtask/hooks/actions/jira.py +74 -0
- flowtask/hooks/actions/rest.py +320 -0
- flowtask/hooks/actions/sampledata.py +37 -0
- flowtask/hooks/actions/sensor.py +23 -0
- flowtask/hooks/actions/task.py +9 -0
- flowtask/hooks/actions/ticket.py +37 -0
- flowtask/hooks/actions/zammad.py +55 -0
- flowtask/hooks/hook.py +62 -0
- flowtask/hooks/models.py +17 -0
- flowtask/hooks/service.py +187 -0
- flowtask/hooks/step.py +91 -0
- flowtask/hooks/types/__init__.py +23 -0
- flowtask/hooks/types/base.py +129 -0
- flowtask/hooks/types/brokers/__init__.py +11 -0
- flowtask/hooks/types/brokers/base.py +54 -0
- flowtask/hooks/types/brokers/mqtt.py +35 -0
- flowtask/hooks/types/brokers/rabbitmq.py +82 -0
- flowtask/hooks/types/brokers/redis.py +83 -0
- flowtask/hooks/types/brokers/sqs.py +44 -0
- flowtask/hooks/types/fs.py +232 -0
- flowtask/hooks/types/http.py +49 -0
- flowtask/hooks/types/imap.py +200 -0
- flowtask/hooks/types/jira.py +279 -0
- flowtask/hooks/types/mail.py +205 -0
- flowtask/hooks/types/postgres.py +98 -0
- flowtask/hooks/types/responses/__init__.py +8 -0
- flowtask/hooks/types/responses/base.py +5 -0
- flowtask/hooks/types/sharepoint.py +288 -0
- flowtask/hooks/types/ssh.py +141 -0
- flowtask/hooks/types/tagged.py +59 -0
- flowtask/hooks/types/upload.py +85 -0
- flowtask/hooks/types/watch.py +71 -0
- flowtask/hooks/types/web.py +36 -0
- flowtask/interfaces/AzureClient.py +137 -0
- flowtask/interfaces/AzureGraph.py +839 -0
- flowtask/interfaces/Boto3Client.py +326 -0
- flowtask/interfaces/DropboxClient.py +173 -0
- flowtask/interfaces/ExcelHandler.py +94 -0
- flowtask/interfaces/FTPClient.py +131 -0
- flowtask/interfaces/GoogleCalendar.py +201 -0
- flowtask/interfaces/GoogleClient.py +133 -0
- flowtask/interfaces/GoogleDrive.py +127 -0
- flowtask/interfaces/GoogleGCS.py +89 -0
- flowtask/interfaces/GoogleGeocoding.py +93 -0
- flowtask/interfaces/GoogleLang.py +114 -0
- flowtask/interfaces/GooglePub.py +61 -0
- flowtask/interfaces/GoogleSheet.py +68 -0
- flowtask/interfaces/IMAPClient.py +137 -0
- flowtask/interfaces/O365Calendar.py +113 -0
- flowtask/interfaces/O365Client.py +220 -0
- flowtask/interfaces/OneDrive.py +284 -0
- flowtask/interfaces/Outlook.py +155 -0
- flowtask/interfaces/ParrotBot.py +130 -0
- flowtask/interfaces/SSHClient.py +378 -0
- flowtask/interfaces/Sharepoint.py +496 -0
- flowtask/interfaces/__init__.py +36 -0
- flowtask/interfaces/azureauth.py +119 -0
- flowtask/interfaces/cache.py +201 -0
- flowtask/interfaces/client.py +82 -0
- flowtask/interfaces/compress.py +525 -0
- flowtask/interfaces/credentials.py +124 -0
- flowtask/interfaces/d2l.py +239 -0
- flowtask/interfaces/databases/__init__.py +5 -0
- flowtask/interfaces/databases/db.py +223 -0
- flowtask/interfaces/databases/documentdb.py +55 -0
- flowtask/interfaces/databases/rethink.py +39 -0
- flowtask/interfaces/dataframes/__init__.py +11 -0
- flowtask/interfaces/dataframes/abstract.py +21 -0
- flowtask/interfaces/dataframes/arrow.py +71 -0
- flowtask/interfaces/dataframes/dt.py +69 -0
- flowtask/interfaces/dataframes/pandas.py +167 -0
- flowtask/interfaces/dataframes/polars.py +60 -0
- flowtask/interfaces/db.py +263 -0
- flowtask/interfaces/env.py +46 -0
- flowtask/interfaces/func.py +137 -0
- flowtask/interfaces/http.py +1780 -0
- flowtask/interfaces/locale.py +40 -0
- flowtask/interfaces/log.py +75 -0
- flowtask/interfaces/mask.py +143 -0
- flowtask/interfaces/notification.py +154 -0
- flowtask/interfaces/playwright.py +339 -0
- flowtask/interfaces/powerpoint.py +368 -0
- flowtask/interfaces/py.typed +0 -0
- flowtask/interfaces/qs.py +376 -0
- flowtask/interfaces/result.py +87 -0
- flowtask/interfaces/selenium_service.py +779 -0
- flowtask/interfaces/smartsheet.py +154 -0
- flowtask/interfaces/stat.py +39 -0
- flowtask/interfaces/task.py +96 -0
- flowtask/interfaces/template.py +118 -0
- flowtask/interfaces/vectorstores/__init__.py +1 -0
- flowtask/interfaces/vectorstores/abstract.py +133 -0
- flowtask/interfaces/vectorstores/milvus.py +669 -0
- flowtask/interfaces/zammad.py +107 -0
- flowtask/models.py +193 -0
- flowtask/parsers/__init__.py +15 -0
- flowtask/parsers/_yaml.c +11978 -0
- flowtask/parsers/_yaml.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/argparser.py +235 -0
- flowtask/parsers/base.c +15155 -0
- flowtask/parsers/base.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/json.c +11968 -0
- flowtask/parsers/json.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/maps.py +49 -0
- flowtask/parsers/toml.c +11968 -0
- flowtask/parsers/toml.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/plugins/__init__.py +16 -0
- flowtask/plugins/components/__init__.py +0 -0
- flowtask/plugins/handler/__init__.py +45 -0
- flowtask/plugins/importer.py +31 -0
- flowtask/plugins/sources/__init__.py +0 -0
- flowtask/runner.py +283 -0
- flowtask/scheduler/__init__.py +9 -0
- flowtask/scheduler/functions.py +493 -0
- flowtask/scheduler/handlers/__init__.py +8 -0
- flowtask/scheduler/handlers/manager.py +504 -0
- flowtask/scheduler/handlers/models.py +58 -0
- flowtask/scheduler/handlers/service.py +72 -0
- flowtask/scheduler/notifications.py +65 -0
- flowtask/scheduler/scheduler.py +993 -0
- flowtask/services/__init__.py +0 -0
- flowtask/services/bots/__init__.py +0 -0
- flowtask/services/bots/telegram.py +264 -0
- flowtask/services/files/__init__.py +11 -0
- flowtask/services/files/manager.py +522 -0
- flowtask/services/files/model.py +37 -0
- flowtask/services/files/service.py +767 -0
- flowtask/services/jira/__init__.py +3 -0
- flowtask/services/jira/jira_actions.py +191 -0
- flowtask/services/tasks/__init__.py +13 -0
- flowtask/services/tasks/launcher.py +213 -0
- flowtask/services/tasks/manager.py +323 -0
- flowtask/services/tasks/service.py +275 -0
- flowtask/services/tasks/task_manager.py +376 -0
- flowtask/services/tasks/tasks.py +155 -0
- flowtask/storages/__init__.py +16 -0
- flowtask/storages/exceptions.py +12 -0
- flowtask/storages/files/__init__.py +8 -0
- flowtask/storages/files/abstract.py +29 -0
- flowtask/storages/files/filesystem.py +66 -0
- flowtask/storages/tasks/__init__.py +19 -0
- flowtask/storages/tasks/abstract.py +26 -0
- flowtask/storages/tasks/database.py +33 -0
- flowtask/storages/tasks/filesystem.py +108 -0
- flowtask/storages/tasks/github.py +119 -0
- flowtask/storages/tasks/memory.py +45 -0
- flowtask/storages/tasks/row.py +25 -0
- flowtask/tasks/__init__.py +0 -0
- flowtask/tasks/abstract.py +526 -0
- flowtask/tasks/command.py +118 -0
- flowtask/tasks/pile.py +486 -0
- flowtask/tasks/py.typed +0 -0
- flowtask/tasks/task.py +778 -0
- flowtask/template/__init__.py +161 -0
- flowtask/tests.py +257 -0
- flowtask/types/__init__.py +8 -0
- flowtask/types/typedefs.c +11347 -0
- flowtask/types/typedefs.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/__init__.py +24 -0
- flowtask/utils/constants.py +117 -0
- flowtask/utils/encoders.py +21 -0
- flowtask/utils/executor.py +112 -0
- flowtask/utils/functions.cpp +14280 -0
- flowtask/utils/functions.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/json.cpp +13349 -0
- flowtask/utils/json.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/mail.py +63 -0
- flowtask/utils/parseqs.c +13324 -0
- flowtask/utils/parserqs.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/stats.py +308 -0
- flowtask/utils/transformations.py +74 -0
- flowtask/utils/uv.py +12 -0
- flowtask/utils/validators.py +97 -0
- flowtask/version.py +11 -0
- flowtask-5.8.4.dist-info/LICENSE +201 -0
- flowtask-5.8.4.dist-info/METADATA +209 -0
- flowtask-5.8.4.dist-info/RECORD +470 -0
- flowtask-5.8.4.dist-info/WHEEL +6 -0
- flowtask-5.8.4.dist-info/entry_points.txt +3 -0
- flowtask-5.8.4.dist-info/top_level.txt +2 -0
- plugins/components/CreateQR.py +39 -0
- plugins/components/TestComponent.py +28 -0
- plugins/components/Use1.py +13 -0
- plugins/components/Workplace.py +117 -0
- plugins/components/__init__.py +3 -0
- plugins/sources/__init__.py +0 -0
- plugins/sources/get_populartimes.py +78 -0
- plugins/sources/google.py +150 -0
- plugins/sources/hubspot.py +679 -0
- plugins/sources/icims.py +679 -0
- plugins/sources/mobileinsight.py +501 -0
- plugins/sources/newrelic.py +262 -0
- plugins/sources/uap.py +268 -0
- plugins/sources/venu.py +244 -0
- plugins/sources/vocinity.py +314 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
import asyncio
|
3
|
+
import googlemaps
|
4
|
+
from typing import Tuple, Union, Dict, List
|
5
|
+
from .GoogleClient import GoogleClient
|
6
|
+
from ..exceptions import ComponentError
|
7
|
+
|
8
|
+
|
9
|
+
class GoogleMapsGeocodingClient(GoogleClient, ABC):
|
10
|
+
"""
|
11
|
+
Google Maps Geocoding Client for location-based tasks including geocoding,
|
12
|
+
reverse geocoding, distance calculation, and place details.
|
13
|
+
"""
|
14
|
+
|
15
|
+
def __init__(self, *args, api_key: str, **kwargs):
|
16
|
+
super().__init__(*args, **kwargs)
|
17
|
+
self.api_key = api_key
|
18
|
+
self._client = None
|
19
|
+
|
20
|
+
async def get_client(self):
|
21
|
+
"""Get the Google Maps client, with caching."""
|
22
|
+
if not self._client:
|
23
|
+
self._client = await asyncio.to_thread(googlemaps.Client, self.api_key)
|
24
|
+
return self._client
|
25
|
+
|
26
|
+
async def geocode_address(self, address: str) -> Dict:
|
27
|
+
"""
|
28
|
+
Geocode an address to retrieve latitude and longitude.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
address (str): The address to geocode.
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
dict: Geocoded location with latitude and longitude.
|
35
|
+
"""
|
36
|
+
client = await self.get_client()
|
37
|
+
result = await asyncio.to_thread(client.geocode, address)
|
38
|
+
if result:
|
39
|
+
location = result[0]['geometry']['location']
|
40
|
+
return {"lat": location['lat'], "lng": location['lng']}
|
41
|
+
else:
|
42
|
+
raise ComponentError("Address could not be geocoded.")
|
43
|
+
|
44
|
+
async def reverse_geocode(self, lat: float, lng: float) -> List[Dict]:
|
45
|
+
"""
|
46
|
+
Reverse geocode coordinates to retrieve address information.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
lat (float): Latitude of the location.
|
50
|
+
lng (float): Longitude of the location.
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
list: List of addresses for the location.
|
54
|
+
"""
|
55
|
+
client = await self.get_client()
|
56
|
+
result = await asyncio.to_thread(client.reverse_geocode, (lat, lng))
|
57
|
+
return result
|
58
|
+
|
59
|
+
async def calculate_distance(self, origin: str, destination: str) -> Dict:
|
60
|
+
"""
|
61
|
+
Calculate the distance between two locations.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
origin (str): Starting location (address or coordinates).
|
65
|
+
destination (str): Ending location (address or coordinates).
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
dict: Distance and duration between the origin and destination.
|
69
|
+
"""
|
70
|
+
client = await self.get_client()
|
71
|
+
result = await asyncio.to_thread(client.distance_matrix, origin, destination)
|
72
|
+
if result['rows']:
|
73
|
+
distance_info = result['rows'][0]['elements'][0]
|
74
|
+
return {
|
75
|
+
"distance": distance_info['distance']['text'],
|
76
|
+
"duration": distance_info['duration']['text']
|
77
|
+
}
|
78
|
+
else:
|
79
|
+
raise ComponentError("Could not calculate distance between locations.")
|
80
|
+
|
81
|
+
async def get_place_details(self, place_id: str) -> Dict:
|
82
|
+
"""
|
83
|
+
Get detailed information about a place by its place ID.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
place_id (str): The place ID of the location.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
dict: Detailed information about the place.
|
90
|
+
"""
|
91
|
+
client = await self.get_client()
|
92
|
+
result = await asyncio.to_thread(client.place, place_id)
|
93
|
+
return result['result'] if 'result' in result else {}
|
@@ -0,0 +1,114 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
import asyncio
|
3
|
+
from google.cloud import language_v1
|
4
|
+
from google.auth.exceptions import GoogleAuthError
|
5
|
+
from .GoogleClient import GoogleClient
|
6
|
+
from ..exceptions import ComponentError
|
7
|
+
|
8
|
+
|
9
|
+
class GoogleLanguage(GoogleClient, ABC):
|
10
|
+
"""
|
11
|
+
Google Cloud Natural Language Client for analyzing text for
|
12
|
+
sentiment, entities, syntax, and content classification.
|
13
|
+
"""
|
14
|
+
|
15
|
+
def __init__(self, *args, **kwargs):
|
16
|
+
super().__init__(*args, **kwargs)
|
17
|
+
self._client = None
|
18
|
+
|
19
|
+
async def get_client(self):
|
20
|
+
"""Get the Natural Language client, with caching."""
|
21
|
+
if not self._client:
|
22
|
+
try:
|
23
|
+
self._client = await asyncio.to_thread(language_v1.LanguageServiceClient, credentials=self.credentials)
|
24
|
+
except GoogleAuthError as e:
|
25
|
+
raise ComponentError(f"Google Natural Language API authentication error: {e}")
|
26
|
+
return self._client
|
27
|
+
|
28
|
+
async def analyze_sentiment(self, text: str):
|
29
|
+
"""
|
30
|
+
Analyze the sentiment of the provided text.
|
31
|
+
|
32
|
+
Args:
|
33
|
+
text (str): The text to analyze.
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
dict: Sentiment score and magnitude.
|
37
|
+
"""
|
38
|
+
client = await self.get_client()
|
39
|
+
document = language_v1.Document(content=text, type_=language_v1.Document.Type.PLAIN_TEXT)
|
40
|
+
response = await asyncio.to_thread(client.analyze_sentiment, document=document)
|
41
|
+
sentiment = response.document_sentiment
|
42
|
+
return {"score": sentiment.score, "magnitude": sentiment.magnitude}
|
43
|
+
|
44
|
+
async def analyze_entities(self, text: str):
|
45
|
+
"""
|
46
|
+
Analyze entities in the provided text.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
text (str): The text to analyze.
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
list: A list of entities with their types and salience scores.
|
53
|
+
"""
|
54
|
+
client = await self.get_client()
|
55
|
+
document = language_v1.Document(content=text, type_=language_v1.Document.Type.PLAIN_TEXT)
|
56
|
+
response = await asyncio.to_thread(client.analyze_entities, document=document)
|
57
|
+
|
58
|
+
entities = []
|
59
|
+
for entity in response.entities:
|
60
|
+
entities.append({
|
61
|
+
"name": entity.name,
|
62
|
+
"type": language_v1.Entity.Type(entity.type_).name,
|
63
|
+
"salience": entity.salience,
|
64
|
+
"metadata": entity.metadata,
|
65
|
+
})
|
66
|
+
return entities
|
67
|
+
|
68
|
+
async def analyze_syntax(self, text: str):
|
69
|
+
"""
|
70
|
+
Analyze syntax of the provided text.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
text (str): The text to analyze.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
list: A list of tokens with their parts of speech and dependency relationships.
|
77
|
+
"""
|
78
|
+
client = await self.get_client()
|
79
|
+
document = language_v1.Document(content=text, type_=language_v1.Document.Type.PLAIN_TEXT)
|
80
|
+
response = await asyncio.to_thread(client.analyze_syntax, document=document)
|
81
|
+
|
82
|
+
tokens = []
|
83
|
+
for token in response.tokens:
|
84
|
+
tokens.append({
|
85
|
+
"text": token.text.content,
|
86
|
+
"part_of_speech": language_v1.PartOfSpeech.Tag(token.part_of_speech.tag).name,
|
87
|
+
"dependency_edge": {
|
88
|
+
"head_token_index": token.dependency_edge.head_token_index,
|
89
|
+
"label": language_v1.DependencyEdge.Label(token.dependency_edge.label).name,
|
90
|
+
}
|
91
|
+
})
|
92
|
+
return tokens
|
93
|
+
|
94
|
+
async def classify_text(self, text: str):
|
95
|
+
"""
|
96
|
+
Classify the content of the provided text into categories.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
text (str): The text to classify.
|
100
|
+
|
101
|
+
Returns:
|
102
|
+
list: A list of categories with confidence scores.
|
103
|
+
"""
|
104
|
+
client = await self.get_client()
|
105
|
+
document = language_v1.Document(content=text, type_=language_v1.Document.Type.PLAIN_TEXT)
|
106
|
+
response = await asyncio.to_thread(client.classify_text, document=document)
|
107
|
+
|
108
|
+
categories = []
|
109
|
+
for category in response.categories:
|
110
|
+
categories.append({
|
111
|
+
"name": category.name,
|
112
|
+
"confidence": category.confidence,
|
113
|
+
})
|
114
|
+
return categories
|
@@ -0,0 +1,61 @@
|
|
1
|
+
from google.cloud import pubsub_v1
|
2
|
+
from google.auth.exceptions import GoogleAuthError
|
3
|
+
import asyncio
|
4
|
+
from .GoogleClient import GoogleClient
|
5
|
+
from ..exceptions import ComponentError
|
6
|
+
|
7
|
+
class GooglePubSubClient(GoogleClient):
|
8
|
+
"""
|
9
|
+
Google Pub/Sub Client for managing topics, subscriptions, and message handling.
|
10
|
+
"""
|
11
|
+
|
12
|
+
def __init__(self, *args, project_id: str, **kwargs):
|
13
|
+
super().__init__(*args, **kwargs)
|
14
|
+
self.project_id = project_id
|
15
|
+
self._publisher = None
|
16
|
+
self._subscriber = None
|
17
|
+
|
18
|
+
async def get_publisher(self):
|
19
|
+
if not self._publisher:
|
20
|
+
try:
|
21
|
+
self._publisher = await asyncio.to_thread(pubsub_v1.PublisherClient, credentials=self.credentials)
|
22
|
+
except GoogleAuthError as e:
|
23
|
+
raise ComponentError(f"Google Pub/Sub authentication error: {e}")
|
24
|
+
return self._publisher
|
25
|
+
|
26
|
+
async def get_subscriber(self):
|
27
|
+
if not self._subscriber:
|
28
|
+
try:
|
29
|
+
self._subscriber = await asyncio.to_thread(pubsub_v1.SubscriberClient, credentials=self.credentials)
|
30
|
+
except GoogleAuthError as e:
|
31
|
+
raise ComponentError(f"Google Pub/Sub authentication error: {e}")
|
32
|
+
return self._subscriber
|
33
|
+
|
34
|
+
async def create_topic(self, topic_name: str):
|
35
|
+
publisher = await self.get_publisher()
|
36
|
+
topic_path = publisher.topic_path(self.project_id, topic_name)
|
37
|
+
await asyncio.to_thread(publisher.create_topic, name=topic_path)
|
38
|
+
print(f"Topic '{topic_name}' created.")
|
39
|
+
|
40
|
+
async def publish_message(self, topic_name: str, message: str):
|
41
|
+
publisher = await self.get_publisher()
|
42
|
+
topic_path = publisher.topic_path(self.project_id, topic_name)
|
43
|
+
future = await asyncio.to_thread(publisher.publish, topic_path, message.encode("utf-8"))
|
44
|
+
print(f"Published message ID: {future.result()}")
|
45
|
+
|
46
|
+
async def create_subscription(self, topic_name: str, subscription_name: str):
|
47
|
+
subscriber = await self.get_subscriber()
|
48
|
+
topic_path = subscriber.topic_path(self.project_id, topic_name)
|
49
|
+
subscription_path = subscriber.subscription_path(self.project_id, subscription_name)
|
50
|
+
await asyncio.to_thread(subscriber.create_subscription, name=subscription_path, topic=topic_path)
|
51
|
+
print(f"Subscription '{subscription_name}' created for topic '{topic_name}'.")
|
52
|
+
|
53
|
+
async def pull_messages(self, subscription_name: str, max_messages: int = 10):
|
54
|
+
subscriber = await self.get_subscriber()
|
55
|
+
subscription_path = subscriber.subscription_path(self.project_id, subscription_name)
|
56
|
+
response = await asyncio.to_thread(
|
57
|
+
subscriber.pull, request={"subscription": subscription_path, "max_messages": max_messages}
|
58
|
+
)
|
59
|
+
for message in response.received_messages:
|
60
|
+
print(f"Received message: {message.message.data}")
|
61
|
+
await asyncio.to_thread(subscriber.acknowledge, subscription=subscription_path, ack_ids=[message.ack_id])
|
@@ -0,0 +1,68 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
from typing import Union
|
3
|
+
from pathlib import PurePath, Path
|
4
|
+
import pandas as pd
|
5
|
+
import asyncio
|
6
|
+
from googleapiclient.errors import HttpError
|
7
|
+
from .GoogleClient import GoogleClient
|
8
|
+
from ..exceptions import ComponentError
|
9
|
+
|
10
|
+
|
11
|
+
class GoogleSheetsClient(GoogleClient, ABC):
|
12
|
+
"""
|
13
|
+
Google Sheets Client for downloading and interacting with Google Sheets.
|
14
|
+
"""
|
15
|
+
|
16
|
+
async def download_file(
|
17
|
+
self,
|
18
|
+
sheet_id: str,
|
19
|
+
worksheet_name: str = None,
|
20
|
+
file_type: str = "dataframe"
|
21
|
+
) -> Union[pd.DataFrame, str]:
|
22
|
+
"""
|
23
|
+
Download the content of a Google Sheet in various formats.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
sheet_id (str): The ID of the Google Sheet.
|
27
|
+
worksheet_name (str): The name of the worksheet (optional, defaults to the first sheet).
|
28
|
+
file_type (str): Desired format - 'dataframe', 'json', 'excel', or 'csv'.
|
29
|
+
|
30
|
+
Returns:
|
31
|
+
pd.DataFrame or str: DataFrame if requested, or the file path for other formats.
|
32
|
+
"""
|
33
|
+
try:
|
34
|
+
sheets_service = await asyncio.to_thread(self.get_sheets_client)
|
35
|
+
sheet = await asyncio.to_thread(
|
36
|
+
sheets_service.spreadsheets().get, spreadsheetId=sheet_id
|
37
|
+
)
|
38
|
+
sheet = sheet.execute()
|
39
|
+
sheet_name = worksheet_name or sheet['sheets'][0]['properties']['title']
|
40
|
+
|
41
|
+
# Fetch data as a DataFrame
|
42
|
+
result = await asyncio.to_thread(
|
43
|
+
sheets_service.spreadsheets().values().get,
|
44
|
+
spreadsheetId=sheet_id,
|
45
|
+
range=sheet_name
|
46
|
+
)
|
47
|
+
result = result.execute()
|
48
|
+
values = result.get('values', [])
|
49
|
+
dataframe = pd.DataFrame(values[1:], columns=values[0]) # Assumes first row is the header
|
50
|
+
|
51
|
+
# Format-based handling
|
52
|
+
if file_type == "dataframe":
|
53
|
+
return dataframe
|
54
|
+
elif file_type == "json":
|
55
|
+
return await asyncio.to_thread(dataframe.to_json)
|
56
|
+
elif file_type == "excel":
|
57
|
+
file_path = Path(f"{sheet_name}.xlsx")
|
58
|
+
await asyncio.to_thread(dataframe.to_excel, file_path, index=False)
|
59
|
+
return str(file_path)
|
60
|
+
elif file_type == "csv":
|
61
|
+
file_path = Path(f"{sheet_name}.csv")
|
62
|
+
await asyncio.to_thread(dataframe.to_csv, file_path, index=False)
|
63
|
+
return str(file_path)
|
64
|
+
else:
|
65
|
+
raise ValueError("Invalid file_type. Use 'dataframe', 'json', 'excel', or 'csv'.")
|
66
|
+
|
67
|
+
except HttpError as error:
|
68
|
+
raise ComponentError(f"Error downloading Google Sheet: {error}")
|
@@ -0,0 +1,137 @@
|
|
1
|
+
"""
|
2
|
+
IMAP/POP Client.
|
3
|
+
|
4
|
+
Class for operations with IMAP Mailboxes.
|
5
|
+
|
6
|
+
"""
|
7
|
+
import socket
|
8
|
+
import asyncio
|
9
|
+
import ssl
|
10
|
+
from collections.abc import Callable
|
11
|
+
import imaplib
|
12
|
+
from ..exceptions import ComponentError
|
13
|
+
from .client import ClientInterface
|
14
|
+
from .azureauth import AzureAuth
|
15
|
+
|
16
|
+
|
17
|
+
class IMAPClient(ClientInterface):
|
18
|
+
"""
|
19
|
+
IMAPClient
|
20
|
+
|
21
|
+
Overview
|
22
|
+
|
23
|
+
The IMAPClient class provides operations for interacting with IMAP mailboxes.
|
24
|
+
It supports both SSL and non-SSL
|
25
|
+
connections and uses XOAUTH2 authentication by default.
|
26
|
+
|
27
|
+
.. table:: Properties
|
28
|
+
:widths: auto
|
29
|
+
|
30
|
+
+------------------+----------+------------------------------------------------------------------------------------------+
|
31
|
+
| Name | Required | Description |
|
32
|
+
+------------------+----------+------------------------------------------------------------------------------------------+
|
33
|
+
| use_ssl | No | Boolean flag to specify whether to use SSL, defaults to True. |
|
34
|
+
+------------------+----------+------------------------------------------------------------------------------------------+
|
35
|
+
| mailbox | No | The mailbox to access, defaults to "Inbox". |
|
36
|
+
+------------------+----------+------------------------------------------------------------------------------------------+
|
37
|
+
| overwrite | No | Boolean flag to specify whether to overwrite existing configurations, defaults to False. |
|
38
|
+
+------------------+----------+------------------------------------------------------------------------------------------+
|
39
|
+
|
40
|
+
Return
|
41
|
+
|
42
|
+
The methods in this class manage the connection to the IMAP server and perform authentication and closure of
|
43
|
+
the connection.
|
44
|
+
|
45
|
+
""" # noqa
|
46
|
+
|
47
|
+
_credentials: dict = {"user": str, "password": str}
|
48
|
+
authmech: str = "XOAUTH2"
|
49
|
+
use_ssl = True
|
50
|
+
|
51
|
+
def __init__(
|
52
|
+
self, *args, host: str = None, port: str = None, **kwargs
|
53
|
+
) -> None:
|
54
|
+
self._connected: bool = False
|
55
|
+
self._client: Callable = None
|
56
|
+
self.use_ssl: bool = kwargs.pop("use_ssl", True)
|
57
|
+
self.mailbox: str = kwargs.pop('mailbox', "Inbox")
|
58
|
+
self.overwrite: bool = kwargs.pop('overwrite', False)
|
59
|
+
self._sslcontext = ssl.create_default_context()
|
60
|
+
self._sslcontext.minimum_version = ssl.TLSVersion.TLSv1_2
|
61
|
+
self._sslcontext.check_hostname = False
|
62
|
+
self._sslcontext.verify_mode = ssl.CERT_NONE
|
63
|
+
self._client: Callable = None
|
64
|
+
self._timeout = kwargs.get('timeout', 20)
|
65
|
+
super(IMAPClient, self).__init__(*args, host=host, port=port, **kwargs)
|
66
|
+
if "use_ssl" in self.credentials:
|
67
|
+
self.use_ssl = self.credentials["use_ssl"]
|
68
|
+
del self.credentials["use_ssl"]
|
69
|
+
|
70
|
+
async def open(self, host: str, port: int, credentials: dict, **kwargs):
|
71
|
+
try:
|
72
|
+
if self.use_ssl:
|
73
|
+
self._client = imaplib.IMAP4_SSL(
|
74
|
+
host, port, timeout=10, ssl_context=self._sslcontext
|
75
|
+
)
|
76
|
+
else:
|
77
|
+
self._client = imaplib.IMAP4(host, port, timeout=10)
|
78
|
+
except socket.error as e:
|
79
|
+
raise ComponentError(f"Socket Error: {e}") from e
|
80
|
+
except ValueError as ex:
|
81
|
+
print("IMAP err", ex)
|
82
|
+
raise RuntimeError(f"IMAP Invalid parameters or credentials: {ex}") from ex
|
83
|
+
except Exception as ex:
|
84
|
+
print("IMAP err", ex)
|
85
|
+
self._logger.error(
|
86
|
+
f"Error connecting to server: {ex}"
|
87
|
+
)
|
88
|
+
raise ComponentError(
|
89
|
+
f"Error connecting to server: {ex}"
|
90
|
+
) from ex
|
91
|
+
# start the connection
|
92
|
+
try:
|
93
|
+
# disable debug:
|
94
|
+
self._client.debug = 0
|
95
|
+
except Exception:
|
96
|
+
pass
|
97
|
+
try:
|
98
|
+
await asyncio.sleep(0.5)
|
99
|
+
self._client.timeout = 20
|
100
|
+
if self.authmech is not None:
|
101
|
+
### we need to build an Auth token:
|
102
|
+
azure = AzureAuth() # default values
|
103
|
+
result, msg = self._client.authenticate(
|
104
|
+
self.authmech,
|
105
|
+
lambda x: azure.binary_token(
|
106
|
+
credentials["user"], credentials["password"]
|
107
|
+
),
|
108
|
+
)
|
109
|
+
print("RESULT ", result, msg)
|
110
|
+
if result == "OK":
|
111
|
+
self._connected = True
|
112
|
+
return self._connected
|
113
|
+
else:
|
114
|
+
raise ComponentError(f"IMAP: Wrong response from Server {msg}")
|
115
|
+
else:
|
116
|
+
# using default authentication
|
117
|
+
r = self._client.login(credentials["user"], credentials["password"])
|
118
|
+
if r.result != "NO":
|
119
|
+
self._connected = True
|
120
|
+
return self._connected
|
121
|
+
else:
|
122
|
+
raise ComponentError(f"IMAP: Wrong response from Server {r.result}")
|
123
|
+
except AttributeError as err:
|
124
|
+
raise ComponentError(
|
125
|
+
f"Login Forbidden, wrong username or password: {err}"
|
126
|
+
) from err
|
127
|
+
except Exception as err:
|
128
|
+
raise ComponentError(f"Error connecting to server: {err}") from err
|
129
|
+
|
130
|
+
async def close(self, timeout: int = 5):
|
131
|
+
try:
|
132
|
+
if self._client:
|
133
|
+
self._client.close()
|
134
|
+
self._client.logout()
|
135
|
+
self._connected = False
|
136
|
+
except imaplib.IMAP4.abort as err:
|
137
|
+
self._logger.warning(err)
|
@@ -0,0 +1,113 @@
|
|
1
|
+
from typing import List, Dict
|
2
|
+
from datetime import datetime, timedelta
|
3
|
+
from .O365Client import O365Client
|
4
|
+
from ..exceptions import ComponentError
|
5
|
+
|
6
|
+
|
7
|
+
class OutlookCalendarClient(O365Client):
|
8
|
+
"""
|
9
|
+
Outlook Calendar Client for managing calendar events through Microsoft Graph API.
|
10
|
+
"""
|
11
|
+
|
12
|
+
async def get_client(self):
|
13
|
+
"""Ensure that the Graph client is initialized and ready to use."""
|
14
|
+
if not self._graph_client:
|
15
|
+
self.connection() # Ensures that `_graph_client` is created during connection setup
|
16
|
+
return self._graph_client
|
17
|
+
|
18
|
+
async def create_event(self, calendar_id: str, event: Dict) -> Dict:
|
19
|
+
"""
|
20
|
+
Create an event in the specified Outlook calendar.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
calendar_id (str): The ID of the calendar.
|
24
|
+
event (dict): The event details.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
dict: Details of the created event.
|
28
|
+
"""
|
29
|
+
client = await self.get_client()
|
30
|
+
event = await self.run_in_executor(
|
31
|
+
client.me.calendars[calendar_id].events.add,
|
32
|
+
**event
|
33
|
+
)
|
34
|
+
return event
|
35
|
+
|
36
|
+
async def list_events(
|
37
|
+
self,
|
38
|
+
calendar_id: str,
|
39
|
+
start_datetime: datetime,
|
40
|
+
end_datetime: datetime,
|
41
|
+
max_results: int = 10
|
42
|
+
) -> List[Dict]:
|
43
|
+
"""
|
44
|
+
List events in a specified time range in the specified calendar.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
calendar_id (str): The ID of the calendar.
|
48
|
+
start_datetime (datetime): Start time for retrieving events.
|
49
|
+
end_datetime (datetime): End time for retrieving events.
|
50
|
+
max_results (int): Maximum number of events to retrieve (default: 10).
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
list: List of events in the specified time range.
|
54
|
+
"""
|
55
|
+
client = await self.get_client()
|
56
|
+
events = await self.run_in_executor(
|
57
|
+
client.me.calendars[calendar_id].calendar_view,
|
58
|
+
start_datetime.isoformat(),
|
59
|
+
end_datetime.isoformat(),
|
60
|
+
max_results=max_results
|
61
|
+
)
|
62
|
+
return [event.to_dict() for event in events]
|
63
|
+
|
64
|
+
async def get_event(self, calendar_id: str, event_id: str) -> Dict:
|
65
|
+
"""
|
66
|
+
Retrieve details of a specific event.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
calendar_id (str): The ID of the calendar.
|
70
|
+
event_id (str): The ID of the event.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
dict: Details of the retrieved event.
|
74
|
+
"""
|
75
|
+
client = await self.get_client()
|
76
|
+
event = await self.run_in_executor(
|
77
|
+
client.me.calendars[calendar_id].events.get,
|
78
|
+
event_id=event_id
|
79
|
+
)
|
80
|
+
return event.to_dict()
|
81
|
+
|
82
|
+
async def update_event(self, calendar_id: str, event_id: str, updated_event: Dict) -> Dict:
|
83
|
+
"""
|
84
|
+
Update an existing event in the specified calendar.
|
85
|
+
|
86
|
+
Args:
|
87
|
+
calendar_id (str): The ID of the calendar.
|
88
|
+
event_id (str): The ID of the event.
|
89
|
+
updated_event (dict): Updated event details.
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
dict: Details of the updated event.
|
93
|
+
"""
|
94
|
+
client = await self.get_client()
|
95
|
+
updated = await self.run_in_executor(
|
96
|
+
client.me.calendars[calendar_id].events[event_id].update,
|
97
|
+
**updated_event
|
98
|
+
)
|
99
|
+
return updated.to_dict()
|
100
|
+
|
101
|
+
async def delete_event(self, calendar_id: str, event_id: str):
|
102
|
+
"""
|
103
|
+
Delete an event from the specified calendar.
|
104
|
+
|
105
|
+
Args:
|
106
|
+
calendar_id (str): The ID of the calendar.
|
107
|
+
event_id (str): The ID of the event to delete.
|
108
|
+
"""
|
109
|
+
client = await self.get_client()
|
110
|
+
await self.run_in_executor(
|
111
|
+
client.me.calendars[calendar_id].events[event_id].delete
|
112
|
+
)
|
113
|
+
print(f"Event {event_id} deleted.")
|