Skip to content

Commit

Permalink
feat: connector jobology
Browse files Browse the repository at this point in the history
  • Loading branch information
Abdellahitech committed Jan 8, 2024
1 parent 51803b2 commit 28ea90d
Show file tree
Hide file tree
Showing 11 changed files with 595 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ We invite developers to join us in our mission to bring AI and data integration
| **Indeed** | Job Board | 🎯 | | |
| **Inzojob** | Job Board | 🎯 | | |
| **Jobijoba** | Job Board | 🎯 | | |
| [**Jobology**](./src/hrflow_connectors/connectors/jobology/README.md) | Job Board | :white_check_mark: | *21/12/2022* | *08/01/2024* | :x: | :x: | :x: | :x: |
| **Jobrapido** | Job Board | 🎯 | | |
| **JobTeaser** | Job Board | 🎯 | | |
| **Jobtransport** | Job Board | 🎯 | | |
Expand Down
204 changes: 204 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -25049,6 +25049,210 @@
],
"type": "ATS",
"logo": "https://raw.githubusercontent.com/Riminder/hrflow-connectors/master/src/hrflow_connectors/connectors/digitalrecruiters/logo.png"
},
{
"name": "Jobology",
"actions": [
{
"name": "catch_profile",
"action_type": "inbound",
"action_parameters": {
"title": "TriggerViewActionParameters",
"type": "object",
"properties": {
"read_mode": {
"description": "If 'incremental' then `read_from` of the last run is given to Origin Warehouse during read. **The actual behavior depends on implementation of read**. In 'sync' mode `read_from` is neither fetched nor given to Origin Warehouse during read.",
"default": "sync",
"allOf": [
{
"$ref": "#/definitions/ReadMode"
}
]
},
"logics": {
"title": "logics",
"description": "List of logic functions. Each function should have the following signature typing.Callable[[typing.Dict], typing.Optional[typing.Dict]]. The final list should be exposed in a variable named 'logics'.",
"template": "\nimport typing as t\n\ndef logic_1(item: t.Dict) -> t.Union[t.Dict, None]:\n return None\n\ndef logic_2(item: t.Dict) -> t.Uniont[t.Dict, None]:\n return None\n\nlogics = [logic_1, logic_2]\n",
"type": "code_editor"
},
"format": {
"title": "format",
"description": "Formatting function. You should expose a function named 'format' with following signature typing.Callable[[typing.Dict], typing.Dict]",
"template": "\nimport typing as t\n\ndef format(item: t.Dict) -> t.Dict:\n return item\n",
"type": "code_editor"
},
"event_parser": {
"title": "event_parser",
"description": "Event parsing function for **CATCH** integrations. You should expose a function named 'event_parser' with following signature typing.Callable[[typing.Dict], typing.Dict]",
"template": "\nimport typing as t\n\ndef event_parser(event: t.Dict) -> t.Dict:\n parsed = dict()\n parsed[\"user_id\"] = event[\"email\"]\n parsed[\"thread_id\"] = event[\"subscription_id\"]\n return parsed\n",
"type": "code_editor"
}
},
"additionalProperties": false,
"definitions": {
"ReadMode": {
"title": "ReadMode",
"description": "An enumeration.",
"enum": [
"sync",
"incremental"
]
}
}
},
"data_type": "profile",
"trigger_type": "hook",
"origin": "Jobology Candidate",
"origin_parameters": {
"title": "ReadProfilesParameters",
"type": "object",
"properties": {
"profile": {
"title": "Profile",
"description": "Event object recieved from the Webhook",
"field_type": "Other",
"type": "object"
}
},
"additionalProperties": false
},
"origin_data_schema": {
"title": "BaseModel",
"type": "object",
"properties": {}
},
"supports_incremental": false,
"target": "HrFlow.ai Profile Parsing",
"target_parameters": {
"title": "WriteProfileParsingParameters",
"type": "object",
"properties": {
"api_secret": {
"title": "Api Secret",
"description": "X-API-KEY used to access HrFlow.ai API",
"field_type": "Auth",
"type": "string"
},
"api_user": {
"title": "Api User",
"description": "X-USER-EMAIL used to access HrFlow.ai API",
"field_type": "Auth",
"type": "string"
},
"source_key": {
"title": "Source Key",
"description": "HrFlow.ai source key",
"field_type": "Other",
"type": "string"
},
"only_insert": {
"title": "Only Insert",
"description": "When enabled the profile is written only if it doesn't exist in the source",
"default": false,
"field_type": "Other",
"type": "boolean"
}
},
"required": [
"api_secret",
"api_user",
"source_key"
],
"additionalProperties": false
},
"target_data_schema": {
"title": "HrFlowProfileParsing",
"type": "object",
"properties": {
"reference": {
"title": "Reference",
"description": "Custom identifier of the Profile.",
"type": "string"
},
"created_at": {
"title": "Created At",
"description": "type: datetime ISO8601, Creation date of the Profile.",
"type": "string"
},
"resume": {
"$ref": "#/definitions/ResumeToParse"
},
"tags": {
"title": "Tags",
"description": "List of tags of the Profile.",
"type": "array",
"items": {
"$ref": "#/definitions/GeneralEntitySchema"
}
},
"metadatas": {
"title": "Metadatas",
"description": "List of metadatas of the Profile.",
"type": "array",
"items": {
"$ref": "#/definitions/GeneralEntitySchema"
}
}
},
"required": [
"reference",
"created_at",
"resume",
"tags",
"metadatas"
],
"definitions": {
"ResumeToParse": {
"title": "ResumeToParse",
"type": "object",
"properties": {
"raw": {
"title": "Raw",
"type": "string",
"format": "binary"
},
"content_type": {
"title": "Content Type",
"type": "string"
}
},
"required": [
"raw",
"content_type"
]
},
"GeneralEntitySchema": {
"title": "GeneralEntitySchema",
"type": "object",
"properties": {
"name": {
"title": "Name",
"description": "Identification name of the Object",
"type": "string"
},
"value": {
"title": "Value",
"description": "Value associated to the Object's name",
"type": "string"
}
},
"required": [
"name"
]
}
}
},
"workflow_code": "import typing as t\n\nfrom hrflow_connectors import Jobology\nfrom hrflow_connectors.core.connector import ActionInitError, Reason\n\nORIGIN_SETTINGS_PREFIX = \"origin_\"\nTARGET_SETTINGS_PREFIX = \"target_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << event_parser_placeholder >>\n\n\ndef workflow(\n \n _request: t.Dict,\n \n settings: t.Dict\n ) -> None:\n actions_parameters = dict()\n try:\n format\n except NameError:\n pass\n else:\n actions_parameters[\"format\"] = format\n\n try:\n logics\n except NameError:\n pass\n else:\n actions_parameters[\"logics\"] = logics\n\n if \"__workflow_id\" not in settings:\n return Jobology.catch_profile(\n workflow_id=\"\",\n action_parameters=dict(),\n origin_parameters=dict(),\n target_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n try:\n event_parser\n _event_parser = event_parser\n except NameError as e:\n action = Jobology.model.action_by_name(\"catch_profile\")\n # Without this trick event_parser is always only fetched from the local scope\n # meaning that try block always raises NameError even if the function is\n # defined in the placeholder\n _event_parser = action.parameters.__fields__[\"event_parser\"].default\n\n if _event_parser is not None:\n try:\n _request = _event_parser(_request)\n except Exception as e:\n return Jobology.catch_profile(\n workflow_id=workflow_id,\n action_parameters=dict(),\n origin_parameters=dict(),\n target_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n origin_parameters = dict()\n for parameter in ['profile']:\n if \"{}{}\".format(ORIGIN_SETTINGS_PREFIX, parameter) in settings:\n origin_parameters[parameter] = settings[\"{}{}\".format(ORIGIN_SETTINGS_PREFIX, parameter)]\n \n if parameter in _request:\n origin_parameters[parameter] = _request[parameter]\n \n\n target_parameters = dict()\n for parameter in ['api_secret', 'api_user', 'source_key', 'only_insert']:\n if \"{}{}\".format(TARGET_SETTINGS_PREFIX, parameter) in settings:\n target_parameters[parameter] = settings[\"{}{}\".format(TARGET_SETTINGS_PREFIX, parameter)]\n \n if parameter in _request:\n target_parameters[parameter] = _request[parameter]\n \n\n return Jobology.catch_profile(\n workflow_id=workflow_id,\n action_parameters=actions_parameters,\n origin_parameters=origin_parameters,\n target_parameters=target_parameters,\n )",
"workflow_code_format_placeholder": "# << format_placeholder >>",
"workflow_code_logics_placeholder": "# << logics_placeholder >>",
"workflow_code_event_parser_placeholder": "# << event_parser_placeholder >>",
"workflow_code_workflow_id_settings_key": "__workflow_id",
"workflow_code_origin_settings_prefix": "origin_",
"workflow_code_target_settings_prefix": "target_"
}
],
"type": "Job Board",
"logo": "https://raw.githubusercontent.com/Riminder/hrflow-connectors/master/src/hrflow_connectors/connectors/jobology/logo.jpeg"
}
]
}
2 changes: 2 additions & 0 deletions src/hrflow_connectors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from hrflow_connectors.connectors.digitalrecruiters import DigitalRecruiters
from hrflow_connectors.connectors.greenhouse.connector import Greenhouse
from hrflow_connectors.connectors.hubspot import Hubspot
from hrflow_connectors.connectors.jobology import Jobology
from hrflow_connectors.connectors.lever import Lever
from hrflow_connectors.connectors.poleemploi import PoleEmploi
from hrflow_connectors.connectors.recruitee import Recruitee
Expand Down Expand Up @@ -40,6 +41,7 @@
Lever,
Salesforce,
DigitalRecruiters,
Jobology,
]

# This makes sure that connector are in module namespace
Expand Down
72 changes: 72 additions & 0 deletions src/hrflow_connectors/connectors/jobology/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# 📖 Summary
- [📖 Summary](#-summary)
- [💼 About Jobology](#-about-jobology)
- [😍 Why is it a big deal for Jobology customers & partners?](#-why-is-it-a-big-deal-for-jobology-customers--partners)
- [🔧 How does it work?](#-how-does-it-work)
- [📊 Data integration capabilities:](#-data-integration-capabilities)
- [🔌 Connector Actions](#-connector-actions)
- [💍 Quick Start Examples](#-quick-start-examples)
- [🔗 Useful Links](#-useful-links)
- [👏 Special Thanks](#-special-thanks)


# 💼 About Jobology

> La mission de jobology est de faciliter le processus de recrutement pour les entreprises

## 😍 Why is it a big deal for Jobology customers & partners?

This new connector will enable:
- ⚡ A Fastlane Talent & Workforce data integration for Jobology customers & partners
- 🤖 Cutting-edge AI-powered Talent Experiences & Recruiter Experiences for Jobology customers

# 🔧 How does it work?
## 📊 Data integration capabilities:
- ⬅️ Send Profiles data from Jobology to a Destination of your choice:





# 🔌 Connector Actions
<p align="center">

| Action | Description |
| ------- | ----------- |
| [**Catch profile**](docs/catch_profile.md) | Imports candidates, in synchronization with jobology |


</p>

<p align="center">
<image src=https://github.com/Riminder/hrflow-connectors/assets/135601200/1d28d312-6c28-4749-a5f1-b72fa8c16730 width=90% height=100% >
</p>


# 💍 Quick Start Examples

To make sure you can successfully run the latest versions of the example scripts, you have to **install the package from PyPi**.


To browse the examples of actions corresponding to released versions of 🤗 this connector, you just need to import the module like this :

<p align="center">
<image src=https://github.com/Riminder/hrflow-connectors/assets/135601200/1f295bdc-b505-4e5c-9d2f-0163844a2da8 width=90% height=100% >
</p>


Once the connector module is imported, you can leverage all the different actions that it offers.

For more code details checkout connector code.


# 🔗 Useful Links

- 📄Visit [Jobology](https://www.jobology.com/) to learn more.
- 💻 [Connector code](https://github.com/Riminder/hrflow-connectors/tree/master/src/hrflow_connectors/connectors/jobology) on our Github.


# 👏 Special Thanks
- 💻 HrFlow.ai : Abdellahi Mezid - Software Engineer
- 🤝 Jobology : Jobology Team
1 change: 1 addition & 0 deletions src/hrflow_connectors/connectors/jobology/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from hrflow_connectors.connectors.jobology.connector import Jobology # noqa
83 changes: 83 additions & 0 deletions src/hrflow_connectors/connectors/jobology/connector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import typing as t

from hrflow_connectors.connectors.hrflow.warehouse import HrFlowProfileParsingWarehouse
from hrflow_connectors.connectors.jobology.warehouse import JobologyProfilesWarehouse
from hrflow_connectors.core import (
ActionName,
ActionType,
BaseActionParameters,
Connector,
ConnectorAction,
ConnectorType,
WorkflowType,
)


def rename_profile_fields(jobology_profile: t.Dict) -> t.Dict:
return {
"job-key": jobology_profile["jobkey"],
"first_name": jobology_profile.get("firstName"),
"last_name": jobology_profile.get("lastName"),
"phone": jobology_profile.get("phone"),
"email": jobology_profile.get("email"),
"coverText": jobology_profile.get("coverText"),
"profile-country": jobology_profile.get("profilecountry"),
"profile-regions": jobology_profile.get("profileregions"),
"profile-domains": jobology_profile.get("profiledomains"),
"job-lien_annonce_site_carriere": jobology_profile.get(
"joblien_annonce_site_carriere"
),
"statistic-source": jobology_profile.get("statisticsource"),
"statistic-jbsource": jobology_profile.get("statisticjbsource"),
}


def add_tags(profile_tags: t.Dict) -> t.List[t.Dict]:
return [dict(name=key, value=value) for key, value in profile_tags.items() if value]


def format_jobology_profile(jobology_profile: t.List) -> t.Dict:
profile_tags = rename_profile_fields(jobology_profile)
tags = add_tags(profile_tags)
resume_dict = dict(
raw=jobology_profile["cv"],
content_type=jobology_profile["content_type"],
)
return dict(
reference=jobology_profile["email"],
resume=resume_dict,
tags=tags,
metadatas=[],
created_at=None,
)


def event_parser(event: t.Dict) -> t.Dict:
return dict(profile=event)


DESCRIPTION = (
"La mission de jobology est de faciliter le processus de recrutement pour les"
" entreprises "
)
Jobology = Connector(
name="Jobology",
type=ConnectorType.JobBoard,
description=DESCRIPTION,
url="https://www.jobology.fr/",
actions=[
ConnectorAction(
name=ActionName.catch_profile,
trigger_type=WorkflowType.catch,
description="Imports candidates, in synchronization with jobology",
parameters=BaseActionParameters.with_defaults(
"TriggerViewActionParameters",
format=format_jobology_profile,
event_parser=event_parser,
),
origin=JobologyProfilesWarehouse,
target=HrFlowProfileParsingWarehouse,
action_type=ActionType.inbound,
)
],
)
Loading

0 comments on commit 28ea90d

Please sign in to comment.