joshiayush / inb Goto Github PK
View Code? Open in Web Editor NEWAutomate the world of LinkedIn!
License: Other
Automate the world of LinkedIn!
License: Other
I noticed that keywords could be something we can use with multiple values.
For example, if I want to reach out to recruiters, I could use the following:
--keywords "Tech Recruiter" --keywords "Recruiter" --keywords "Talent Acquisition"
What do you think?
inb/inb/linkedin/person/person.py
Lines 204 to 254 in 2f66b3a
We need to change the way we target elements in the DOM
. Look at the above code it's so messy and probably need some refactoring. If we do not figure out a more systematic way of finding elements in the DOM
then this code is bound to be labelled as legacy tommorow. Chained function calls lying around that way makes code less readable and messy. Probably we need to build some kind of abstraction around it that will just take in the selectors for selecting elements in the DOM
and will return WebElement
if found.
find_child_by_css_selector(parent: Union[str, WebElement], child: str)
def find_child_by_css_selector(
parent: Union[str, webdriver.WebElement],
child: str) -> webdriver.WebElement:
"""Function returns the child of the given parent element.
This function takes in a 'parent' instance whether in a string format means parent's css
selector or in form of a webdriver.WebElement instance and returns the child located at
the given css selector i.e., 'child'.
Note: In case the element or the parent is not present anymore in the DOM then this
function will not prevent the built-in find_element_by_css_selector() function by raising
NoSuchElementException.
Args:
parent (Union[str, WebElement]): Either css selector of the parent or the parent's
webdriver.WebElement instance itself.
child (str): CSS selector of the child.
Returns:
webdriver.WebElement: The requested child, WebElement instance returned by the built-in
find_element_by_css_selector() function.
Raises:
NoSuchElementException: Default NoSuchElementException behaviour of function
find_element_by_css_selector().
>>> child = find_child_by_css_selector(
... "div[class='discover-entity-type-card__info-container']", "a")
"""
pass
find_child_by_tag_name(parent: Union[str, WebElement], child: str)
def find_child_by_tag_name(
parent: Union[str, webdriver.WebElement],
child: str) -> webdriver.WebElement:
"""Function returns the child of the given parent element.
This function takes in a 'parent' instance whether in a string format means parent's tag
name or in form of a webdriver.WebElement instance and returns the child by the given
tag name i.e., 'child'.
Note: In case the element or the parent is not present anymore in the DOM then this
function will not prevent the built-in find_element_by_tag_name() function by raising
NoSuchElementException.
Args:
parent (Union[str, WebElement]): Either tag name of the parent or the parent's
webdriver.WebElement instance itself.
child (str): Tag name of the child.
Returns:
webdriver.WebElement: The requested child, WebElement instance returned by the built-in
find_element_by_tag_name() function.
Raises:
NoSuchElementException: Default NoSuchElementException behaviour of function
find_element_by_tag_name().
>>> child = find_child_by_tag_name("div", "a")
"""
pass
find_child_by_xpath(parent: Union[str, WebElement], child: str)
def find_child_by_xpath(
parent: Union[str, webdriver.WebElement],
child: str) -> webdriver.WebElement:
"""Function returns the child of the given parent element.
This function takes in a 'parent' instance whether in a string format means parent's xpath
or in form of a webdriver.WebElement instance and returns the child located at the given
xpath i.e., 'child'.
Note: In case the element or the parent is not present anymore in the DOM then this
function will not prevent the built-in find_element_by_xpath() function by raising
NoSuchElementException.
Args:
parent (Union[str, WebElement]): Either xpath of the parent or the parent's
webdriver.WebElement instance itself.
child (str): Xpath of the child.
Returns:
webdriver.WebElement: The requested child, WebElement instance returned by the built-in
find_element_by_xpath() function.
Raises:
NoSuchElementException: Default NoSuchElementException behaviour of function
find_element_by_xpath().
>>> child = find_child_by_xpath(
... '//*[@id="main"]/div/div/div[2]//a[text()="Try Premium Free For 1 Month"]',
... "//div/a/div[1]/div[1]/img[1]")
"""
pass
Lines 319 to 336 in 2f66b3a
As of now command show
which is meant to show the information of user(s) stored in the database (database is also not set yet) does not work. It will be a good feature to implement in conjunction with config
and delete
command to give user's ability to store their email and password in a database so they don't have to type their email and password every time they want to automate a LinkedIn session.
show
command will be helpful to read out the database and dump the content of the database on the console or any raw file in case user want that.
inb/database
, (use SQLite).PERM
error depending on the step 3
.Leaving on a long road trip without using a map is going to waste a lot of valuable time even if we get there eventually and I feel this is the same what we are doing. Project inb is currently in its beta state so before proposing any change we must write design document on it.
Add software design description inside of the docs/project folder.
Things to add:
Lines 338 to 355 in 2f66b3a
As of now the config
command which is meant to create or update entries in the database does not work. It will be a good feature to implement in conjunction with the delete
command and before show
command.
inb/database
, (use SQLite).write
permissions or not if not then throw PERM
error otherwise follow the below steps.CREATE TABLE database_name.inb_users(
Email CHAR(50) PRIMARY KEY NOT NULL,
Password CHAR(50) NOT NULL,
CreatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW'))
);
db
folder.2
step, insert the fields given by the user.config
command should follow the following command line arguments:
$ inb.py config --email "user_email" --password "user_password"
Replace MIT
license that is at the top of some python file in the repository and replace it with BSD 3-Clause
license like the one here and also update the README
and the LICENSE
file with BSD 3-Clause
license.
Lines 1 to 37 in a560ad1
Unclosed input/output buffer while testing custom print functions makes python throw ResourceWarning
.
test.py
file
from tests.console.print import TestPrintFunctions
Argument force
has no effect on the coloured print functions where it was supposed to print the text in the given color
and style
when the force="+f"
it doesn't do that. This force
argument is to force the coloured print functions to print the given text in the given color
and style
this functionality is needed when the user turns the theme to normal
where every coloured print function just print the given text in the normal style but still we need to highlight some of the information like errors, waiting infos, etc.
theme --normal
.As the force
argument is enabled and the coloured print functions are coded for this functionality it must highlight the text.
See it should print the 'whydoesn'tforceargumentworks' is not a 'linkedin' command!
in bright red color but it didn't.
The following command:
python3 ~/inb/inb/inb.py search --email "[email protected]" --password "R" --keyword "Team Building" --location "London" --title "Director" --message ~/message-ndp-1.txt limit 1
Returns the following error:
INFO:Checking network status
inb: Error: InternetNotConnectedException: Weak network found
This is on Debian 11
running in an LXD
container with 16GB
of RAM?
Automatically filing an issue from the user's end is a requirement which we must fulfil. An example of the application of this feature is here #32.
We should probably make use of the PyGithub API to implement this feature.
Steps to follow before filing an issue:
Invitation status for search
command should display more information than just,
<status> <full name>
<occupation>
Success: <count> Failure: <count> Elapsed time: <count>
We should scrape as much of data as we can to later store in our logs record.
For search
functionality all we need to do is to transform the transform_to_object
function inside get_search_results_elements()
function to also scrape profile url, degree, location, summary, and shared connections.
inb/inb/linkedin/person/person.py
Lines 197 to 268 in 2f66b3a
Later we can display the collected information on the console like the following:
<status> <full name> • <degree>
<occupation>
<location>
<summary>
<shared connections>
Profile Id: <id (from the profile url)>
URL: <profile url>
Success: <count> Failure: <count> Elapsed time: <count>
One such template for that could be the following:
SEARCH_INVITATION_STATUS_TEMPL = """ {{status}} {{full_name}} • {{degree}}
{{person_occupation}}
{{person_location}}
{{person_summary}}
{{shared_connections}}
ID: {{profile_id}}
URL: {{profile_url}}
Success: {{success}} Failure: {{failure}} Elapsed time: {{elapsed_time}}\n"""
Note: You should print the next status after the current status rather than clearing up the current status to make room for next status.
Hi,
Please provide the instructions on how to use the linkedin.message? Also are there any plans on implementing the bulk send messages to connections?
Because LinkedIn keeps changing its element's selector every now and then, we must capture the stack trace to find out which element's selector has got changed.
It would be a good feature if we could just implement a logging call that will log the stack trace in case of NoSuchElementException
. This logging call must log in a separate file inside of the logs
directory inside of the project's root directory.
We also must provide user the ability to automatically file an issue with the generated logs in case inb breaks because of NoSuchElementException
.
You'll find more details on this issue here #31.
i have cloned the repo in my local and followed the instruction when i run this script
inb.py search --email [email protected] --password xxxx --keyword 'Software developer' --refresh-cookies
simply it provides the output in the terminal like this
Warning: 'email' is not in the list of known options, but still passed to Electron/Chromium.
Warning: 'password' is not in the list of known options, but still passed to Electron/Chromium.
Warning: 'keyword' is not in the list of known options, but still passed to Electron/Chromium.
Warning: 'refresh-cookies' is not in the list of known options, but still passed to Electron/Chromium.
kindly reslove the issue
Invitation status for send
command should display more information than just,
<status> <full name>
<occupation>
Success: <count> Failure: <count> Elapsed time: <count>
We should scrape as much of data as we can to later store in our logs record.
For send
functionality all we need to do is to transform the transform_to_object()
function inside get_suggestion_box_element()
function to also scrape profile url, mutual connections.
inb/inb/linkedin/person/person.py
Lines 123 to 159 in 2f66b3a
Later we can display the collected information on the console like the following:
<status> <full name>
<occupation>
<mutual connections>
ID: <id (from the profile url)>
URL: <profile url>
Success: <count> Failure: <count> Elapsed time: <count>
One such template for that could be the following:
SEND_INVITATION_STATUS_TEMPL = """ {{status}} {{full_name}}
{{person_occupation}}
{{mutual_connections}}
ID: {{profile_id}}
URL: {{profile_url}}
Success: {{success}} Failure: {{failure}} Elapsed time: {{elapsed_time}}\n"""
Note: You should print the next status after the current status rather than clearing up the current status to make room for next status.
There is a typo on the --refresh-cookies
parameter on line 139 (it reads --refersh-cookies
)
Users can not use the bundled version of inb
into a single executable unless the chromedriver
is served from the environment PATH
. We need to install chromedriver
inside a local system path and then extend the environment PATH
with it so that the chromedriver
will be visible to our executable.
Lines 392 to 417 in fc5d58e
The above function should install chromedriver
inside a local system path and then extend the environment PATH
with it independent of the platform the user is running.
Traceback (most recent call last): File "c:\inb\inb2\inb\linkedin\connect\linkedinsearchconnect.py", line 482, in _GetElementByXPath EC.presence_of_element_located((by.By.XPATH, xpath))) File "C:\Users\Work\anaconda3\envs\inb\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException: Message:
Our recent branch renaming has broken the pytest
workflow which requires to be updated. Currently, the pytest.yml
file runs when pushed and pulled to master
branch:
https://github.com/joshiayush/inb/blob/main/.github/workflows/pytest.yml#L17-L21
But it should be changed to one that we have in our pylint.yml
which runs on every push and pull regardless of the branch:
https://github.com/joshiayush/inb/blob/main/.github/workflows/pylint.yml#L17
When testing fixture TestProtectedGetGoogleChromeBinaryVersionFunction
the following exception appears.
======================================================================
ERROR: test_call_to_subprocess_check_output_in_linux (tests.test_linkedin.test_settings.TestProtectedGetGoogleChromeBinaryVersionFunction)
This should test if the call to `subprocess.check_output()` method are
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Python/inb/inb/lib/utils.py", line 142, in wrapper
func(*args, **kwargs)
File "/usr/lib/python3.7/unittest/mock.py", line 1256, in patched
return func(*args, **keywargs)
File "/Python/inb/inb/tests/test_linkedin/test_settings.py", line 70, in test_call_to_subprocess_check_output_in_linux
_ = settings._GetGoogleChromeBinaryVersion() # pylint: disable=protected-access
File "/Python/inb/inb/linkedin/settings.py", line 287, in _GetGoogleChromeBinaryVersion
version = re.search(version_regex, version)
File "/usr/lib/python3.7/re.py", line 185, in search
return _compile(pattern, flags).search(string)
TypeError: expected string or bytes-like object
----------------------------------------------------------------------
When debugging, it appears that the following variable version
that is supposed to contain a string "Google Chrome 97.11.1111.11"
changes its type to mock.Mock
object which is weird :( and due to which the above exception appears.
Lines 282 to 288 in 6a6f9bf
For now the solution could be to just ignore TestProtectedGetGoogleChromeBinaryVersionFunction
fixture and continue with the rest of the test fixtures :(.
when i'm building the image from the readme file it is giving me error!
[+] Building 0.1s (2/2) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 2B 0.0s
=> CANCELED [internal] load .dockerignore 0.0s
=> => transferring context: 0.0s
failed to solve with frontend dockerfile.v0: failed to read dockerfile: open /var/lib/docker/tmp/buildkit-mount2042251597/Dockerfile: no such file or directory
Element Send Now
button has changed to No
.
Add corresponding changes to the following lines, instead of targeting element at "//button[@aria-label='Send now']"
target the new No
button.
inb/inb/linkedin/connect/linkedinsearchconnect.py
Lines 417 to 420 in 2f66b3a
inb/inb/linkedin/connect/linkedinsearchconnect.py
Lines 455 to 458 in 2f66b3a
This code is a bit redundant so try to refactor the above code in a single function call.
There are known issues that seem to be problematic (resuming the whole history if the branch is master
; all others are enslaved branches).
If the name is main
, all other branches would be side branches instead of enslaved branches. Can you fix that?
I have also tried this package in Linux but it failed to give me any output
i have tried in ubuntu 20.4 and when i run this script
python3 inb.py search --email [email protected] --xxxxx --keyword 'Software Engineer' --refresh-cookies
Still this script not giving any errors !!!
kindly resolve the issue
Deprecate the support of language_tool_python
for correcting template syntax; we don't need it anymore.
You can remove the following code:
inb/inb/linkedin/message/template.py
Lines 106 to 110 in 6341867
Also,
inb/inb/linkedin/message/template.py
Lines 198 to 199 in 6341867
Also, change the constructor
's argument list by removing the grammar_check
argument from here and subsequently update the call to Template
constructor:
inb/inb/linkedin/message/template.py
Lines 90 to 93 in 6341867
inb/inb/linkedin/connect/linkedinsearchconnect.py
Lines 396 to 399 in 2f66b3a
Also, remove the following lines of code from _install()
function in inb.sh
.
Lines 62 to 89 in c0073b1
Make sure to update the requirements.txt
as well.
I saw a case where a person doesn't have all the info in the profile (like occupation, name, location, etc.), and since the self._something is None, we see this error in the console, and the process stops.
We need a fallback string for when the value is None
.
Add a fallback string on _replace_template_var_with_template_value should fix the issue
To make inb more robust, add following features to gather information on LinkedIn inside of the ig
module. Once fetched store these values inside of a SQL
database.
contact number
(if possible) of the account holder.email address
(if possible) of the account holder.interests
of the account holder.company details
of the account holder.inb/
└── linkedin/
├── __init__.py
└── ig/ # Information gathering modules will go here
├── __init__.py
It has been observed that user's given limit
for the search
command over the command line has no actual effect on the LinkedInSearchConnect
's send invitation functionality.
$ python3 inb/inb.py search --email "[email protected]" --password "F:(:);GVlk\`" --keyword "Software Developer" limit 20
The above limit
value is not going to force the search
command to limit the invitations to 20
instead search
command will fallback to its default behaviour i.e., 40
.
I guess the only possible solution is to debug the program from command.py
file to all the way to linkedinsearchconnect.py
file.
Lines 280 to 317 in 2f66b3a
inb/inb/inbparser/inbargparser.py
Lines 233 to 381 in 2f66b3a
inb/inb/linkedin/connect/linkedinsearchconnect.py
Lines 73 to 82 in 2f66b3a
The Driver
service's method test_constructor_method_add_argument_internall_calls
fails unexpectedly with the following error:
======================================================================
ERROR: test_constructor_method_add_argument_internal_calls (tests.test_linkedin.test_driver.TestDriverClass)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.7/unittest/mock.py", line 1256, in patched
return func(*args, **keywargs)
File "/Python/inb/inb/tests/test_linkedin/test_driver.py", line 90, in test_constructor_method_add_argument_internal_calls
Driver.DISABLE_SETUID_SANDBOX, Driver.IGNORE_CERTIFICATE_ERRORS])
File "/Python/inb/inb/linkedin/__init__.py", line 65, in __init__
self.enable_webdriver_chrome()
File "/Python/inb/inb/linkedin/__init__.py", line 83, in enable_webdriver_chrome
options=self._options)
File "/Python/inb/lib/python3.7/site-packages/selenium/webdriver/chrome/webdriver.py", line 81, in __init__
desired_capabilities=desired_capabilities)
File "/Python/inb/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 157, in __init__
self.start_session(capabilities, browser_profile)
File "/Python/inb/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 252, in start_session
response = self.execute(Command.NEW_SESSION, parameters)
File "/Python/inb/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/Python/inb/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally
(Driver info: chromedriver=2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb),platform=Linux 5.11.0-34-generic x86_64)
Moreover, it takes more than 60
seconds to run all the tests after adding this particular test
Ran 41 tests in 61.135s
Consider writing wiki
pages on inb. Add inb usage in it.
Lines 357 to 374 in 2f66b3a
As of now command delete
which is meant to delete the user's information from the database or the entire database, does not work. It will be a good feature to implement in conjunction with config
command to give user's the ability to create and remove database entries or to remove the entire database with the help of the delete
command.
write
permissions.rm -f
command on the database.Lines 137 to 138 in d1290b2
Current version of enable_webdriver_chrome()
doesn't validate the chromedriver_path
before passing it to the webdriver.Chrome
constructor. This may lead to WebdriverException
for false driver path. Moreover, we are not checking if the chromedriver
binary is present in the executable path or not. We can do these checks and make sure everything is set up before executing further.
It is unclear how to use parameters like --regions
or --industries
.
Can we provide better docs on this?
Using the project without cloning the repo would be significant, something like docker pull inb
and then docker run inb ...
.
The experience nowadays is already better than needing to install Python manually. However, users still have to clone the repo, which adds friction to the usage and popularization of this tool.
We could publish a docker image straight away, and the users would pull it without cloning the repo or needing the source code to run the project.
as MVP: I can clone/build/publish the image directly under the inb
name and update the README.md
, adding new instructions to use the project without cloning the repo.
This adds great value already, as we'd have the value for the users to pull from Docker straightaway. The issue with this is that it adds manual work.
We should add a GitHub action to publish the image at every push. I wouldn't say we need to run to do this, as we don't have releases/changes often.
Any chance of us setting up the project with docker instead of manually download and installing with Python?
Hi, i am getting LinkedInChallengeException at run time below is the output any fixes for this?
PS D:\PRJ\inb> docker run -it inb search --email [email protected]>--keyword 'Software developer' --refresh-cookies --nofollow Password: Repeat for confirmation: Traceback (most recent call last): File "inb.py", line 190, in <module> Inb() File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1128, in __call__ return self.main(*args, **kwargs) File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1053, in main rv = self.invoke(ctx) File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1659, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1395, in invoke return ctx.invoke(self.callback, **ctx.params) File "/usr/local/lib/python3.8/site-packages/click/core.py", line 754, in invoke return __callback(*args, **kwargs) File "inb.py", line 143, in search linkedin = linkedin_api.LinkedIn(email, File "/app/api/linkedin_api.py", line 123, in __init__ self.client.authenticate(username=username, password=password) File "/app/api/client.py", line 174, in authenticate self._fallback_authentication(username, password) File "/app/api/client.py", line 142, in _fallback_authentication raise linkedin_api_exceptions.LinkedInChallengeException( api.exceptions.LinkedInChallengeException: CHALLENGE
In the current version of _InstallGoogleChromeCompatibleChromeDriver()
the releases are hard coded in function _GetPlatformSpecificChromeDriverUrlForGoogleChromeMajor()
. In case the user is using an updated version of Google Chrome then the function will return None
resulting the program to crash.
Implementing our own version of python-chromedriver-autoinstaller
will help.
discover_entity_list()
Method does not return <ul />
elements as expected, it just goes into that while True
loop and then not coming out of it.
def discover_entity_list(self: LinkedInConnectionsAuto, xpath: str = "", wait_time: int = 10) -> object:
"""Method discover_entity_list() returns a WebElement that is located at the given xpath.
:Args:
- self: {LinkedInConnectionsAuto} object
- xpath: {str} xpath to the WebElement
- wait_time: {int} time to wait until the WebElement loads
:Returns:
- {WebElement}
"""
while True:
try:
return WebDriverWait(self.driver, wait_time).until(
expected_conditions.presence_of_element_located(
(By.XPATH, xpath)))
except TimeoutException:
continue
I've cross checked the xpath
, xpath
is fine but the problem is once the function goes into that loop it doesn't come out because WebDriverWait
is not able to find that element with the given xpath
.
Element with that xpath
is present in that page in fact it is the element that is present below the invitations
box. I don't know why this method suddenly decided to go weird but before today the problem wasn't there it just worked fine.
inb/inb/lib/algo/levenshtein.py
Lines 26 to 123 in 2f66b3a
It has been observed that function levenshtein()
does not do anything useful except for slowing down the element click process when used inside of the check_for_filter()
method.
inb/inb/linkedin/connect/linkedinsearchconnect.py
Lines 208 to 263 in 2f66b3a
The idea behind using levenshtein distance
was to make sure that user gets correct results even after making a typo in the query for location
command, but it has been observed that the chances of something like that is quite a few or almost none. In cases where user enters a location that is not present in the filters section of LinkedIn, program has to always compute levenshtein distance
for the given location and the locations present in the filters section of LinkedIn which really slows down the process.
Completely delete file levenshtein.py
and refactor the function check_for_filter()
to the following:
def check_for_filter(filter: str,
filter_dict: Dict[str, webdriver.Chrome]) -> None:
"""Nested function check_for_filter() checks if the filter option is present or not.
:Args:
- filter: {str} Filter option to search for.
- filter_dict: {Dict[str, webdriver.Chrome]} Hash-map containing filter one side and
the element to click on, on the other side.
"""
nonlocal self
filters_present: List[str] = filter_dict.keys()
def click_overlapped_element(element: webdriver.Chrome) -> None:
"""Nested function click_overlapped_element() fixes the WebdriverException:
Element is not clickable at point (..., ...).
:Args:
- element: {webdriver.Chrome} Element.
"""
nonlocal self
# @TODO: Validate if the current version of this function is efficient
self._driver.execute_script("arguments[0].click();", element)
if isinstance(filter, str):
if filter in filters_present:
click_overlapped_element(filter_dict[filter])
else
raise Exception('Given filter "' + filter + '" is not present.')
return
if isinstance(filter, list):
for fltr in filter:
if fltr in filters_present:
click_overlapped_element(filter_dict[fltr])
continue
else
raise Exception('Given filter "' + fltr + '" is not present.')
return
This way we immediately halt the process in case there is an error in the query given by the user.
A better feature could be to dump the present locations on the console and allow user to select one or more of them to continue the invitation sending process.
Consider writing a README.md
file for inb same as the one's shown here. Currently the README.md
file is very unattractive and does not show useful information about project inb.
Note: This modification should be done after addressing issue #28. Make a separate branch with a name same as this issue number, propose your changes and create a pull request.
A short description of what needs to be added is defined below:
I got the app working before on Arm64... from memory I just needed to install chromium and copy it to the required location...
sudo apt install python3-pip python3-setuptools git chromium
get's the dependencies for debian and then sudo cp /usr/bin/chromedriver ~/inb/driver/chromedriver
gets an arm64 compatible chromedriver binary in place...
Add message templates
in SQL
database. Currently it only supports json
files lying around the code base; we need a more efficient way to store and fetch the template messages
for customizing invitation request because the way we currently store template data will get ugly when the message template database will increase.
inb/inb/linkedin/message/templates.json
Lines 1 to 17 in c0073b1
The above data should be moved to a SQLite database named message_templates
inside the directory db
in the top level directory, to do so follow the following steps:
message_templates.db
.CREATE TABLE database_name.message_templates(
Id CHAR(50) PRIMARY KEY NOT NULL,
Template TEXT NOT NULL,
CreatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW'))
);
All the database operations must be performed inside of the directory inb/database
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.