flowtask 5.8.4__cp310-cp310-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-310-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-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/argparser.py +235 -0
- flowtask/parsers/base.c +15155 -0
- flowtask/parsers/base.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/json.c +11968 -0
- flowtask/parsers/json.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/maps.py +49 -0
- flowtask/parsers/toml.c +11968 -0
- flowtask/parsers/toml.cpython-310-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-310-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-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/json.cpp +13349 -0
- flowtask/utils/json.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/mail.py +63 -0
- flowtask/utils/parseqs.c +13324 -0
- flowtask/utils/parserqs.cpython-310-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,160 @@
|
|
1
|
+
# Logging:
|
2
|
+
from navconfig.logging import logging
|
3
|
+
|
4
|
+
## Notify System
|
5
|
+
from notify import Notify
|
6
|
+
from notify.providers.email import Email
|
7
|
+
from notify.providers.slack import Slack
|
8
|
+
from notify.providers.teams import Teams
|
9
|
+
from notify.models import (
|
10
|
+
Actor,
|
11
|
+
Chat,
|
12
|
+
Channel,
|
13
|
+
TeamsCard,
|
14
|
+
TeamsChannel
|
15
|
+
)
|
16
|
+
from ...conf import (
|
17
|
+
SEND_NOTIFICATIONS,
|
18
|
+
EVENT_CHAT_ID,
|
19
|
+
EVENT_CHAT_BOT,
|
20
|
+
NOTIFY_ON_ERROR,
|
21
|
+
NOTIFY_ON_SUCCESS,
|
22
|
+
NOTIFY_ON_FAILURE,
|
23
|
+
NOTIFY_ON_WARNING,
|
24
|
+
DEFAULT_RECIPIENT,
|
25
|
+
EMAIL_USERNAME,
|
26
|
+
EMAIL_PASSWORD,
|
27
|
+
EMAIL_PORT,
|
28
|
+
EMAIL_HOST,
|
29
|
+
ENVIRONMENT,
|
30
|
+
SLACK_DEFAULT_CHANNEL,
|
31
|
+
SLACK_DEFAULT_CHANNEL_NAME,
|
32
|
+
MS_TEAMS_DEFAULT_TEAMS_ID,
|
33
|
+
MS_TEAMS_DEFAULT_CHANNEL_ID,
|
34
|
+
MS_TEAMS_DEFAULT_CHANNEL_NAME,
|
35
|
+
SHOW_VERSION
|
36
|
+
)
|
37
|
+
from ...utils.functions import check_empty
|
38
|
+
from .abstract import AbstractEvent
|
39
|
+
from ...version import __version__
|
40
|
+
|
41
|
+
|
42
|
+
class NotifyEvent(AbstractEvent):
|
43
|
+
"""Using Notify to send notifications for task Execution."""
|
44
|
+
|
45
|
+
def __init__(self, *args, event: str = "done", **kwargs):
|
46
|
+
super(NotifyEvent, self).__init__(*args, **kwargs)
|
47
|
+
self._logger = logging.getLogger("FlowTask.Notify")
|
48
|
+
self._event_ = event
|
49
|
+
if event == "done":
|
50
|
+
self.event = NOTIFY_ON_SUCCESS
|
51
|
+
elif event == "warning":
|
52
|
+
self.event = NOTIFY_ON_WARNING
|
53
|
+
elif event == "error":
|
54
|
+
self.event = NOTIFY_ON_ERROR
|
55
|
+
elif event == "exception":
|
56
|
+
self.event = NOTIFY_ON_FAILURE
|
57
|
+
else:
|
58
|
+
self.event = NOTIFY_ON_SUCCESS
|
59
|
+
|
60
|
+
def getNotify(self, notify, **kwargs):
|
61
|
+
if notify == "telegram":
|
62
|
+
# defining the Default chat object:
|
63
|
+
recipient = Chat(**{"chat_id": EVENT_CHAT_ID, "chat_name": "Navigator"})
|
64
|
+
# send notifications to Telegram bot
|
65
|
+
args = {"bot_token": EVENT_CHAT_BOT, **kwargs}
|
66
|
+
ntf = Notify("telegram", **args)
|
67
|
+
elif notify == "slack":
|
68
|
+
recipient = Channel(
|
69
|
+
channel_id=SLACK_DEFAULT_CHANNEL,
|
70
|
+
channel_name=SLACK_DEFAULT_CHANNEL_NAME,
|
71
|
+
)
|
72
|
+
ntf = Slack()
|
73
|
+
elif notify == "email":
|
74
|
+
account = {
|
75
|
+
"host": EMAIL_HOST,
|
76
|
+
"port": EMAIL_PORT,
|
77
|
+
"username": EMAIL_USERNAME,
|
78
|
+
"password": EMAIL_PASSWORD,
|
79
|
+
**kwargs,
|
80
|
+
}
|
81
|
+
recipient = Actor(**DEFAULT_RECIPIENT)
|
82
|
+
ntf = Email(debug=True, **account)
|
83
|
+
elif notify == 'teams':
|
84
|
+
team_id = kwargs.pop("team_id", MS_TEAMS_DEFAULT_TEAMS_ID)
|
85
|
+
recipient = TeamsChannel(
|
86
|
+
name=MS_TEAMS_DEFAULT_CHANNEL_NAME,
|
87
|
+
team_id=team_id,
|
88
|
+
channel_id=MS_TEAMS_DEFAULT_CHANNEL_ID
|
89
|
+
)
|
90
|
+
ntf = Teams(
|
91
|
+
as_user=True,
|
92
|
+
team_id=team_id,
|
93
|
+
)
|
94
|
+
else:
|
95
|
+
# Any other Notify Provider:
|
96
|
+
recipient = Actor(**DEFAULT_RECIPIENT)
|
97
|
+
ntf = Notify(notify, **kwargs)
|
98
|
+
return [ntf, recipient]
|
99
|
+
|
100
|
+
async def __call__(self, *args, **kwargs):
|
101
|
+
if SEND_NOTIFICATIONS is False:
|
102
|
+
return
|
103
|
+
task = kwargs.pop("task", None)
|
104
|
+
result = kwargs.pop("result", None)
|
105
|
+
message = kwargs.pop("message", None)
|
106
|
+
trace = kwargs.pop("stacktrace", None)
|
107
|
+
error = kwargs.pop("error", None)
|
108
|
+
program = task.getProgram()
|
109
|
+
task_name = task.taskname
|
110
|
+
component = kwargs.pop("component", None)
|
111
|
+
if error is not None:
|
112
|
+
self.event = NOTIFY_ON_ERROR
|
113
|
+
if program and task and component:
|
114
|
+
message = f"🛑 ::{ENVIRONMENT} - Task {program}.{task_name}, Error on {component}: {error!s}"
|
115
|
+
elif program and task:
|
116
|
+
message = (
|
117
|
+
f"🛑 ::{ENVIRONMENT} - Error on {program}.{task_name}: {error!s}"
|
118
|
+
)
|
119
|
+
elif trace is not None:
|
120
|
+
self.event = NOTIFY_ON_FAILURE
|
121
|
+
message = f"🛑 ::{ENVIRONMENT} - {program}.{task_name}: {error!s}"
|
122
|
+
else:
|
123
|
+
message = f"🛑 ::{ENVIRONMENT} - {program}.{task_name}: {error!s}"
|
124
|
+
elif self._event_ == "warning":
|
125
|
+
message = f" ⚠️ :: {ENVIRONMENT} - *{program}.{task_name}*: Warning {component}->{str(message)!s}"
|
126
|
+
else:
|
127
|
+
if message is not None and result is not None:
|
128
|
+
# success event:
|
129
|
+
self.event = NOTIFY_ON_SUCCESS
|
130
|
+
message = f" ✅ :: {ENVIRONMENT} - {program}.{task_name}: {message!s}"
|
131
|
+
elif not check_empty(result):
|
132
|
+
message = f" ✅ :: {ENVIRONMENT} - {program}.{task_name}: {message!s}"
|
133
|
+
else:
|
134
|
+
message = f" ⚠️ :: {ENVIRONMENT} - {program}.{task_name}: {message!s}, Empty Result."
|
135
|
+
|
136
|
+
if SHOW_VERSION:
|
137
|
+
message = f"{message} - Version: {__version__}"
|
138
|
+
ntf, recipients = self.getNotify(self.event, **kwargs)
|
139
|
+
args = {"recipient": [recipients], "message": message}
|
140
|
+
if self.event == 'teams':
|
141
|
+
channel = recipients
|
142
|
+
msg = TeamsCard(
|
143
|
+
text=str(message),
|
144
|
+
summary=f"Task Summary: {program}.{task_name}",
|
145
|
+
title=f"Task {program}.{task_name}",
|
146
|
+
)
|
147
|
+
async with ntf as conn:
|
148
|
+
return await conn.send(
|
149
|
+
recipient=channel,
|
150
|
+
message=msg
|
151
|
+
)
|
152
|
+
elif ntf.provider_type == "email":
|
153
|
+
args["subject"] = message
|
154
|
+
elif ntf.provider == "telegram":
|
155
|
+
args["disable_notification"] = True
|
156
|
+
else:
|
157
|
+
args["subject"] = message
|
158
|
+
async with ntf as t:
|
159
|
+
result = await t.send(**args)
|
160
|
+
return result
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import socket
|
2
|
+
from datetime import datetime, timezone
|
3
|
+
from redis import asyncio as aioredis
|
4
|
+
from navconfig.logging import logging
|
5
|
+
from ...utils.json import json_encoder
|
6
|
+
from ...conf import (
|
7
|
+
ENVIRONMENT,
|
8
|
+
PUBSUB_REDIS
|
9
|
+
)
|
10
|
+
from .abstract import AbstractEvent
|
11
|
+
|
12
|
+
EVENT_HOST = socket.gethostbyname(socket.gethostname())
|
13
|
+
|
14
|
+
|
15
|
+
class PublishEvent(AbstractEvent):
|
16
|
+
async def __call__(self, *args, **kwargs):
|
17
|
+
status = kwargs.pop("status", "event")
|
18
|
+
task = kwargs.pop("task", None)
|
19
|
+
program = task.getProgram()
|
20
|
+
task_name = task.taskname.replace(
|
21
|
+
".", ":"
|
22
|
+
) # Convert dots to colons for Redis channel name
|
23
|
+
channel_name = f"{program}:{task_name}"
|
24
|
+
task_id = task.task_id
|
25
|
+
redis = await aioredis.from_url(
|
26
|
+
PUBSUB_REDIS,
|
27
|
+
encoding="utf-8",
|
28
|
+
decode_responses=True
|
29
|
+
)
|
30
|
+
try:
|
31
|
+
stat = task.stats # getting the stat object:
|
32
|
+
stats = json_encoder(stat.to_json())
|
33
|
+
except AttributeError:
|
34
|
+
stats = None
|
35
|
+
msg = {
|
36
|
+
"task": f"{program}.{task_name}",
|
37
|
+
"task_id": task_id,
|
38
|
+
"status": status,
|
39
|
+
"environment": ENVIRONMENT,
|
40
|
+
"host": EVENT_HOST,
|
41
|
+
"stats": stats,
|
42
|
+
"end_time": datetime.now(timezone.utc),
|
43
|
+
}
|
44
|
+
message = json_encoder(msg)
|
45
|
+
try:
|
46
|
+
await redis.publish(channel_name, message)
|
47
|
+
except Exception as e:
|
48
|
+
logging.warning(f"Event Publisher Error: {e}")
|
49
|
+
finally:
|
50
|
+
await redis.close()
|
51
|
+
try:
|
52
|
+
await redis.connection_pool.disconnect()
|
53
|
+
except Exception:
|
54
|
+
pass
|
@@ -0,0 +1,104 @@
|
|
1
|
+
from typing import Union
|
2
|
+
from collections.abc import Callable, Iterable
|
3
|
+
import asyncio
|
4
|
+
from pathlib import Path
|
5
|
+
from notify.models import Actor
|
6
|
+
from notify import Notify
|
7
|
+
from ...exceptions import FileNotFound, ActionError
|
8
|
+
from .interfaces import ClientInterface
|
9
|
+
from .abstract import AbstractEvent
|
10
|
+
|
11
|
+
|
12
|
+
def expand_path(filename: Union[str, Path]) -> Iterable[Path]:
|
13
|
+
if isinstance(filename, str):
|
14
|
+
p = Path(filename)
|
15
|
+
else:
|
16
|
+
p = filename
|
17
|
+
return list(Path(p.parent).expanduser().glob(p.name))
|
18
|
+
|
19
|
+
|
20
|
+
class SendFile(ClientInterface, AbstractEvent):
|
21
|
+
def __init__(self, *args, **kwargs):
|
22
|
+
self.list_attachment: list = []
|
23
|
+
self.notify: Callable = None
|
24
|
+
super(SendFile, self).__init__(*args, **kwargs)
|
25
|
+
|
26
|
+
async def __call__(self, *args, **kwargs):
|
27
|
+
# determine the recipients:
|
28
|
+
# TODO: add support for mailing lists
|
29
|
+
try:
|
30
|
+
self._recipients = [Actor(**user) for user in self.recipients]
|
31
|
+
except Exception as err:
|
32
|
+
raise RuntimeError(f"Error formatting Recipients: {err}") from err
|
33
|
+
if not self._recipients:
|
34
|
+
raise RuntimeError("SendNotify: Invalid Number of Recipients.")
|
35
|
+
|
36
|
+
# File Attachment:
|
37
|
+
# TODO: multiple attachments
|
38
|
+
if hasattr(self, "directory"):
|
39
|
+
d = self.mask_replacement(
|
40
|
+
self.directory # pylint: disable=access-member-before-definition
|
41
|
+
)
|
42
|
+
p = Path(d) # pylint: disable=E0203
|
43
|
+
if p.exists() and p.is_dir():
|
44
|
+
self.directory = p
|
45
|
+
else:
|
46
|
+
self._logger.error(f"Path doesn't exists: {self.directory}")
|
47
|
+
else:
|
48
|
+
self.directory = None
|
49
|
+
|
50
|
+
if hasattr(self, "filename"):
|
51
|
+
file = self.mask_replacement(self.filename)
|
52
|
+
files = []
|
53
|
+
if self.directory:
|
54
|
+
fs = self.directory.joinpath(file)
|
55
|
+
files = expand_path(fs)
|
56
|
+
else:
|
57
|
+
files = expand_path(file)
|
58
|
+
for file in files:
|
59
|
+
if file.exists():
|
60
|
+
self.list_attachment.append(file)
|
61
|
+
else:
|
62
|
+
raise FileNotFound(f"File doesn't exists: {file}")
|
63
|
+
|
64
|
+
# Mask transform of message
|
65
|
+
for key, value in self.message.items():
|
66
|
+
self.message[key] = self.mask_replacement(value)
|
67
|
+
|
68
|
+
try:
|
69
|
+
await self.open()
|
70
|
+
async with self.notify as mail:
|
71
|
+
try:
|
72
|
+
result = await mail.send(
|
73
|
+
recipient=self._recipients,
|
74
|
+
attachments=self.list_attachment,
|
75
|
+
**self.message,
|
76
|
+
)
|
77
|
+
self._logger.debug(f"Notification Status: {result}")
|
78
|
+
except Exception as err:
|
79
|
+
raise ActionError(f"SendNotify Error: {err}") from err
|
80
|
+
return None
|
81
|
+
finally:
|
82
|
+
await self.close()
|
83
|
+
|
84
|
+
async def close(self):
|
85
|
+
"""close.
|
86
|
+
Closing the connection.
|
87
|
+
"""
|
88
|
+
if self.notify:
|
89
|
+
try:
|
90
|
+
await self.notify.close()
|
91
|
+
except Exception as err:
|
92
|
+
print(err)
|
93
|
+
|
94
|
+
async def open(self):
|
95
|
+
"""open.
|
96
|
+
Starts (open) a connection to an external resource.
|
97
|
+
"""
|
98
|
+
try:
|
99
|
+
self.notify = Notify(
|
100
|
+
"email", loop=asyncio.get_event_loop(), **self.credentials
|
101
|
+
)
|
102
|
+
except Exception as err:
|
103
|
+
raise ActionError(f"Error Creating Notification App: {err}") from err
|
104
|
+
return self
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import asyncio
|
2
|
+
import pandas as pd
|
3
|
+
from navconfig import DEBUG
|
4
|
+
from navconfig.logging import logging
|
5
|
+
from .abstract import AbstractEvent
|
6
|
+
from ...exceptions import (
|
7
|
+
NotSupported,
|
8
|
+
TaskNotFound,
|
9
|
+
TaskFailed,
|
10
|
+
FileError,
|
11
|
+
FileNotFound,
|
12
|
+
DataNotFound,
|
13
|
+
)
|
14
|
+
|
15
|
+
|
16
|
+
class RunTask(AbstractEvent):
|
17
|
+
def __init__(self, *args, **kwargs):
|
18
|
+
super(RunTask, self).__init__(*args, **kwargs)
|
19
|
+
self.program = kwargs.pop("program", None)
|
20
|
+
self.task = kwargs.pop("task", None)
|
21
|
+
|
22
|
+
def run_task_in_thread(self, task_coroutine):
|
23
|
+
loop = asyncio.new_event_loop() # Create a new event loop for the thread
|
24
|
+
asyncio.set_event_loop(loop)
|
25
|
+
loop.run_until_complete(task_coroutine)
|
26
|
+
loop.close()
|
27
|
+
|
28
|
+
async def task_execution(self):
|
29
|
+
# avoid circular import
|
30
|
+
from flowtask.tasks.task import Task # noqa
|
31
|
+
|
32
|
+
result = {}
|
33
|
+
task = Task(
|
34
|
+
task=self.task,
|
35
|
+
program=self.program,
|
36
|
+
loop=asyncio.get_event_loop(),
|
37
|
+
enable_stat=False,
|
38
|
+
ignore_results=True,
|
39
|
+
debug=DEBUG,
|
40
|
+
)
|
41
|
+
try:
|
42
|
+
state = await task.start()
|
43
|
+
if not state:
|
44
|
+
logging.warning(
|
45
|
+
f"Task {self.program}.{self.task} return False on Start Time."
|
46
|
+
)
|
47
|
+
except Exception as err:
|
48
|
+
logging.error(err)
|
49
|
+
raise
|
50
|
+
try:
|
51
|
+
state = await task.run()
|
52
|
+
try:
|
53
|
+
result["stats"] = task.stats.stats
|
54
|
+
except Exception as err:
|
55
|
+
result["stats"] = None
|
56
|
+
result["error"] = err
|
57
|
+
### gettting the result of Task execution
|
58
|
+
if isinstance(state, pd.DataFrame):
|
59
|
+
numrows = len(state.index)
|
60
|
+
columns = list(state.columns)
|
61
|
+
num_cols = len(columns)
|
62
|
+
state = {
|
63
|
+
"type": "Dataframe",
|
64
|
+
"numrows": numrows,
|
65
|
+
"columns": columns,
|
66
|
+
"num_cols": num_cols,
|
67
|
+
}
|
68
|
+
else:
|
69
|
+
state = f"{state!r}"
|
70
|
+
result["result"] = state
|
71
|
+
await task.close()
|
72
|
+
return result
|
73
|
+
except DataNotFound as err:
|
74
|
+
raise
|
75
|
+
except NotSupported as err:
|
76
|
+
raise
|
77
|
+
except TaskNotFound as err:
|
78
|
+
raise TaskNotFound(f"Task: {self.task}: {err}") from err
|
79
|
+
except TaskFailed as err:
|
80
|
+
raise TaskFailed(f"Task {self.task} failed: {err}") from err
|
81
|
+
except FileNotFound:
|
82
|
+
raise
|
83
|
+
except FileError as err:
|
84
|
+
raise FileError(f"Task {self.task}, File Not Found error: {err}") from err
|
85
|
+
except Exception as err:
|
86
|
+
raise TaskFailed(f"Error: Task {self.task} failed: {err}") from err
|
87
|
+
|
88
|
+
async def __call__(self, *args, **kwargs):
|
89
|
+
self._logger.debug(f":: Running Task: {self.program}.{self.task}")
|
90
|
+
return await self.task_execution()
|
91
|
+
# task_coroutine = self.task_execution()
|
92
|
+
# task_thread = threading.Thread(
|
93
|
+
# target=self.run_task_in_thread,
|
94
|
+
# args=(task_coroutine,)
|
95
|
+
# )
|
96
|
+
# task_thread.start()
|
97
|
+
# task_thread.join() # Wait for the thread to finish
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import codecs
|
2
|
+
import orjson
|
3
|
+
from notify.models import TeamsCard, TeamsChannel
|
4
|
+
from notify.providers.teams import Teams
|
5
|
+
from notify.conf import MS_TEAMS_DEFAULT_TEAMS_ID, MS_TEAMS_DEFAULT_CHANNEL_ID
|
6
|
+
from ...utils.json import json_encoder
|
7
|
+
from ...interfaces.env import EnvSupport
|
8
|
+
from .abstract import AbstractEvent
|
9
|
+
|
10
|
+
|
11
|
+
class TeamsMessage(AbstractEvent):
|
12
|
+
def __init__(self, *args, **kwargs):
|
13
|
+
super(TeamsMessage, self).__init__(*args, **kwargs)
|
14
|
+
self.channel = kwargs.get('channel', MS_TEAMS_DEFAULT_CHANNEL_ID)
|
15
|
+
self.team_id = kwargs.get('team_id', MS_TEAMS_DEFAULT_TEAMS_ID)
|
16
|
+
self.team_id = self.get_env_value(self.team_id, default=self.team_id)
|
17
|
+
self.channel = self.get_env_value(self.channel, default=self.channel)
|
18
|
+
self.channel_name = kwargs.get('channel_name', 'General')
|
19
|
+
self.channel_name = self.get_env_value(self.channel_name, default=self.channel_name)
|
20
|
+
self._text = self.mask_replacement(kwargs.pop("text", ''))
|
21
|
+
self._title = self.mask_replacement(kwargs.pop("title", 'Task Info:'))
|
22
|
+
|
23
|
+
async def __call__(self, *args, **kwargs):
|
24
|
+
tm = Teams(
|
25
|
+
as_user=True,
|
26
|
+
team_id=self.team_id,
|
27
|
+
)
|
28
|
+
channel = TeamsChannel(
|
29
|
+
name=self.channel_name,
|
30
|
+
team_id=self.team_id,
|
31
|
+
channel_id=self.channel,
|
32
|
+
)
|
33
|
+
status = kwargs.pop("status", "done")
|
34
|
+
task = kwargs.pop("task", None)
|
35
|
+
program = task.getProgram()
|
36
|
+
task_name = f"{program}.{task.taskname}"
|
37
|
+
task_id = task.task_id
|
38
|
+
message = kwargs.pop("message", f"Task Completed {task_name}, {task_id}")
|
39
|
+
message = self.mask_replacement(message)
|
40
|
+
summary = kwargs.pop("summary", f"Task Summary: {task_name}")
|
41
|
+
summary = self.mask_replacement(summary)
|
42
|
+
try:
|
43
|
+
stat = task.stats # getting the stat object:
|
44
|
+
stats = stat.to_json()
|
45
|
+
except AttributeError:
|
46
|
+
stats = []
|
47
|
+
if status == "done":
|
48
|
+
icon = "✅"
|
49
|
+
elif status in ("error", "failed", "exception", "task error"):
|
50
|
+
icon = "🛑"
|
51
|
+
elif status in (
|
52
|
+
"warning",
|
53
|
+
"file_not_found",
|
54
|
+
"not_found",
|
55
|
+
"data_not_found",
|
56
|
+
"done_warning",
|
57
|
+
):
|
58
|
+
icon = "⚠️"
|
59
|
+
elif status in ("empty_file"):
|
60
|
+
icon = "📄"
|
61
|
+
else:
|
62
|
+
icon = "✅"
|
63
|
+
txt = f"{icon} {message}"
|
64
|
+
if self.type == "card":
|
65
|
+
msg = TeamsCard(
|
66
|
+
title=f"Task {task_name} uid:{task_id}",
|
67
|
+
text=txt,
|
68
|
+
summary=summary,
|
69
|
+
)
|
70
|
+
if hasattr(self, "with_stats"):
|
71
|
+
# iterate over task stats:
|
72
|
+
for stat, value in stats["steps"].items():
|
73
|
+
section = msg.addSection(activityTitle=stat, text=stat)
|
74
|
+
stats_json = orjson.dumps(value, option=orjson.OPT_INDENT_2 | orjson.OPT_APPEND_NEWLINE).decode()
|
75
|
+
section.addFacts(
|
76
|
+
facts=[{"name": stat, "value": stats_json}]
|
77
|
+
)
|
78
|
+
if hasattr(self, 'with_codereview'):
|
79
|
+
# Add Code Review
|
80
|
+
section = msg.addSection(activityTitle="Code Review", text="Code Review")
|
81
|
+
codereview = codecs.decode(json_encoder(stats['Review']), 'unicode_escape')
|
82
|
+
section.addFacts(
|
83
|
+
facts=[{"name": "Code Review", "value": codereview}]
|
84
|
+
)
|
85
|
+
else:
|
86
|
+
# only one single block of text:
|
87
|
+
section = msg.addSection(
|
88
|
+
activityTitle=self._title,
|
89
|
+
text=self._text,
|
90
|
+
)
|
91
|
+
section.addFacts(
|
92
|
+
facts=[{"name": "Info", "value": self._text}]
|
93
|
+
)
|
94
|
+
async with tm as conn:
|
95
|
+
return await conn.send(
|
96
|
+
recipient=channel,
|
97
|
+
message=msg
|
98
|
+
)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import aiohttp
|
2
|
+
from ...utils.json import json_encoder
|
3
|
+
from .abstract import AbstractEvent
|
4
|
+
|
5
|
+
|
6
|
+
class WebHook(AbstractEvent):
|
7
|
+
def __init__(self, *args, **kwargs):
|
8
|
+
self.url = kwargs.pop("url", None)
|
9
|
+
super(WebHook, self).__init__(*args, **kwargs)
|
10
|
+
|
11
|
+
async def __call__(self, *args, **kwargs):
|
12
|
+
if not self.url:
|
13
|
+
raise ValueError("URL was not provided for WebHook event action.")
|
14
|
+
status = kwargs.pop("status", "event")
|
15
|
+
task = kwargs.pop("task", None)
|
16
|
+
program = task.getProgram()
|
17
|
+
task_name = f"{program}.{task.taskname}"
|
18
|
+
task_id = task.task_id
|
19
|
+
try:
|
20
|
+
stat = task.stats # getting the stat object:
|
21
|
+
stats = json_encoder(stat.to_json())
|
22
|
+
except AttributeError:
|
23
|
+
stats = None
|
24
|
+
|
25
|
+
# Extract optional authentication parameters
|
26
|
+
auth_type = self._kwargs.get("auth_type", None)
|
27
|
+
auth_value = self._kwargs.get("auth_value", None)
|
28
|
+
|
29
|
+
headers = {}
|
30
|
+
if auth_type and auth_value:
|
31
|
+
if auth_type.lower() == "basic":
|
32
|
+
headers["Authorization"] = f"Basic {auth_value}"
|
33
|
+
elif auth_type.lower() == "bearer":
|
34
|
+
headers["Authorization"] = f"Bearer {auth_value}"
|
35
|
+
else:
|
36
|
+
raise ValueError(f"Unsupported authentication type: {auth_type}")
|
37
|
+
|
38
|
+
# Prepare the payload. You can customize this based on your needs.
|
39
|
+
payload = {
|
40
|
+
"task": task_name,
|
41
|
+
"id": str(task_id),
|
42
|
+
"status": status,
|
43
|
+
"message": kwargs.get("message", "Task Completed."),
|
44
|
+
"stats": stats,
|
45
|
+
}
|
46
|
+
async with aiohttp.ClientSession() as session:
|
47
|
+
async with session.post(
|
48
|
+
self.url, json=payload, headers=headers
|
49
|
+
) as response:
|
50
|
+
if response.status != 200:
|
51
|
+
# Handle non-200 responses if necessary
|
52
|
+
response = await response.text()
|
53
|
+
self._logger.warning(
|
54
|
+
f"Error on WebHook response: {response}, status: {response.status}"
|
55
|
+
)
|
56
|
+
else:
|
57
|
+
# Handle successful webhook call if necessary
|
58
|
+
return
|