Exemple #1
0
    def get(self):
        """
            Parameters:
                - location           (str)
                - query              (str)
                - results_per_page   (int)
                - page               (int)
                - sort_criteria      (str - "relevance", "date", "salary")
            Returns a JSON object: 
                {
                    jobs: [
                        {
                            company,
                            title,
                            locations,
                            url,
                            date,
                            description,
                            salary,
                            salary_type,
                            salary_currency_code,
                            salary_min,
                            salary_max,
                            site,
                        },
                        ...
                    ]
                }
        """
        # Run `pydoc careerjet_api` to see documentation.
        printColoured(" * Getting a list of jobs")
        request_params = dict(request.args)
        pretty_print_dict(request_params)

        # TODO: Checking if all mandatory requests parameters have been sent through
        if not all(
                param in request_params and request_params for param in
            ["location", "query", "results_per_page", "page", "sort_criteria"
             ]):
            printColoured(" * Missing mandatory fields", colour="red")
            raise InvalidUserInput(
                description="Request parameter is missing mandatory fields")

        try:
            return get_job_postings(request.args.get("location"),
                                    request.args.get("query"),
                                    request.args.get("results_per_page"),
                                    request.args.get("page"),
                                    request.args.get("sort_criteria"))
        except Exception as err:
            printColoured(
                " * CareerJet API Client failed to fetch jobs. Error: {}".
                format(err),
                colour="red")
            raise InvalidUserInput(
                description="Couldn't find any jobs. Try a different query")
Exemple #2
0
def fetch_stats(user_id: str, board_id: str):
    """
        Fetches all stats associated with the given board
    """
    target_board = db.boards.find_one({"_id": ObjectId(board_id)})
    if target_board["user_id"] != user_id:
        raise InvalidUserInput(description="That board doesn't belong to you")
    if not target_board:
        raise InvalidUserInput(
            description="Board {} wasn't found".format(board_id))
    return target_board["statistics"]
Exemple #3
0
def update_job(user_id, board_id, job_id, updated_job):
    """
        Updates an existing tracked job for a given user's board
    """
    target_board = db.boards.find_one({
        "_id": ObjectId(board_id),
        "user_id": user_id
    })
    new_jobs = target_board["tracked_jobs"].copy()
    # Find the target job
    target_index = -1
    for job in new_jobs:
        target_index += 1
        if job["job_id"] == job_id:
            break
    if target_index == -1:
        raise InvalidUserInput(
            description="Failed to find job with ID: {}".format(job_id))
    new_jobs[target_index] = updated_job
    db.boards.update_one({
        "_id": ObjectId(board_id),
        "user_id": user_id
    }, {"$set": {
        "tracked_jobs": new_jobs.copy()
    }})
    return updated_job
Exemple #4
0
def add_job(board_id: str, user_id: str, job_to_track: dict) -> dict:
    """
        Adds a job to be tracked
        Parameters:
            - board_id
            - user_id
            - job_to_track
    """
    # TODO: What happens on failure?

    # Additional fields
    job_to_track["current_status"] = "application"
    job_to_track["notes"] = ""
    job_to_track["priority"] = 5
    job_to_track["events"] = []
    # Assign a random ID. TODO: not robust
    job_to_track["job_id"] = "{}-{}".format(board_id, str(uuid.uuid4()))

    if job_already_tracked(user_id, board_id, job_to_track):
        raise InvalidUserInput(description="You're already tracking that job")

    # Push the new job into the board's tracked_jobs list
    db.boards.update_one({
        "_id": ObjectId(board_id),
        "user_id": user_id
    }, {"$push": {
        "tracked_jobs": job_to_track
    }})
    return job_to_track["job_id"]
Exemple #5
0
def get_board(user_id: str, board_id: str):
    board = db.boards.find_one({"user_id": user_id, "_id": ObjectId(board_id)})
    if not board:
        raise InvalidUserInput(
            description="Couldn't find the board with id: {}".format(board_id))
    board["_id"] = str(board["_id"])
    return board
Exemple #6
0
def add_user(username: str, email: str, password: str, image_url="") -> str:
    """
        Registers a new user and commits them to the database.
        Parameters:
            - username
            - email
            - password
        Returns:
            - token
            - user_id
    """
    if user_exists(email):
        raise InvalidUserInput(
            description="A user with that email already exists")
    inserted_user = db.users.insert_one({
        "username": username,
        "email": email,
        "password": password,
        "image_url": image_url,
        "experience": "",
        "title": "Job seeker",
        "phone": "",
        "skills": [],
        "resume": {},
        "favourited_companies": [],
        "resume_fields": {},
        "starred_by": [],
        "tracking": [],
        "tracked_by": []
    })
    return str(inserted_user.inserted_id)
Exemple #7
0
    def post(self):
        """
            Pushes a new job to be tracked under a specific board owned by a user
            Parameters:
                - user_id
                - board_id
                - job_to_track
        """
        printColoured(" * Tracking a new job", colour="yellow")
        request_params = dict(request.get_json())
        try:
            board_id = request_params["board_id"]
            user_id = request_params["user_id"]
            job_to_track = request_params["job_to_track"]
        except KeyError as err:
            raise InvalidUserInput(
                description="Missing mandatory fields: {}".format(err))

        job_id = add_job(board_id, user_id, job_to_track)

        push_stat(
            board_id, {
                "timestamp": int(time.time() - OFFSET),
                "activity": "application",
                "job_id": job_id
            })

        return job_to_track
Exemple #8
0
def login_user(email: str, password: str) -> str:
    """
        Retrieves a user matching the supplied fields.
        Parameters:
            - email
            - password
        Returns:
            - token
            - user_id
    """
    target_user = db.users.find_one({"email": email})
    if not target_user:
        raise InvalidUserInput(
            description="An account with that email doesn't exist")
    if not target_user["password"] == password:
        raise InvalidUserInput(description="Password incorrect")
    return str(target_user["_id"])
Exemple #9
0
def get_favourite_company(user_id: str):
    # Find the user, then get and return the favourited companies name array
    user = db.users.find_one({"_id": ObjectId(user_id)})
    if not user:
        raise InvalidUserInput(
            description="Couldn't find the user with id: {}".format(user_id))

    return user["favourited_companies"]
Exemple #10
0
def get_user_profile(user_id: str):
    """
        Get the user's profile fields.
    """
    user = db.users.find_one({"_id": ObjectId(user_id)})
    if not user:
        raise InvalidUserInput(
            description="Couldn't find user of ID: {}".format(user_id))
    user["_id"] = str(user["_id"])
    return user
Exemple #11
0
def get_job_postings(location, query, results_per_page, page, sort_criteria):
    """ 
        Gets job postings
    """
    cj = CareerjetAPIClient("en_AU")
    jobs_json = cj.search({
        "location":
        location,
        "keywords":
        query,
        "affid":
        "213e213hd12344552",
        "pagesize":
        results_per_page,
        "page":
        page,
        "sort":
        sort_criteria,
        "user_ip":
        "11.22.33.44",
        "url":
        "http://www.example.com/jobsearch",
        "user_agent":
        "Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
    })
    try:
        for each_job in jobs_json["jobs"]:
            # Strip all leading non-alphanumeric characters
            each_job["description"] = re.sub(
                "^[^A-Za-z0-9]*", "", each_job["description"]).capitalize()
            # Truncate duplicate whitespaces
            each_job["description"] = re.sub("\s+", " ",
                                             each_job["description"])
            each_job["description"] = re.sub("<b>", "",
                                             each_job["description"])
            each_job["description"] = re.sub("</b>", "",
                                             each_job["description"])
            # Capitalise all words occurring after punctuation such as . or !
            p = re.compile(r'(?<=[\.\?!]\s)(\w+)')
            each_job["description"] = p.sub(
                lambda match: match.group().capitalize(),
                each_job["description"])
    except Exception as err:
        printColoured("Failed to fetch jobs '{}'. Error: {}".format(
            query, err),
                      colour="red")
        raise InvalidUserInput(
            description="Failed to find jobs for '{}'".format(query))
    return dict(jobs_json)
Exemple #12
0
def save_favourite_company(user_id: str, company_name: str):

    # check quantity
    fav_companies = get_favourite_company(user_id)
    if len(fav_companies) > 10:
        raise InvalidUserInput(
            description="You can't have more than 10 favourite companies")

    # Find the user, then push the company_name into the favourited_companies field
    db.users.update_one({
        "_id": ObjectId(user_id),
    }, {"$push": {
        "favourited_companies": company_name
    }})
    return company_name
Exemple #13
0
def vote_comment(voter_id: str, comment_id: str, increment_amount: int):
    """
        Increases the vote by the amount specified. Negative values denote downvoting
    """
    comment = db.comments.find_one({"_id": ObjectId(comment_id)})
    if voter_id in [voter["voter_id"] for voter in comment["voters"]]:
        raise InvalidUserInput(description="You have already voted")

    db.comments.update_one({"_id": ObjectId(comment_id)}, {
        "$inc": {
            "vote": increment_amount
        },
        "$addToSet": {
            "voters": {
                "voter_id": voter_id,
                "vote_amount": increment_amount
            }
        }
    })
Exemple #14
0
def clear_vote(voter_id: str, comment_id: str):
    comment = db.comments.find_one({"_id": ObjectId(comment_id)})
    voter = [
        voter for voter in comment["voters"] if voter["voter_id"] == voter_id
    ][0]
    if not voter:
        raise InvalidUserInput(
            description="Can't clear a vote that doesn't exist")
    vote_amount = voter["vote_amount"]

    db.comments.update_one({"_id": ObjectId(comment_id)}, {
        "$pull": {
            "voters": {
                "voter_id": voter_id
            }
        },
        "$inc": {
            "vote": -vote_amount
        }
    })
Exemple #15
0
def get_content(url):
    try:
        web_page = requests.get(url, allow_redirects=True, timeout=5)
    except requests.exceptions.Timeout as err:
        raise ServerException(
            description=
            "Failed to fetch web page in time! Skipping preprocessing")
    soup = BeautifulSoup(web_page.content, "html.parser")
    content = str(soup.section)
    try:
        for field in soup.find('ul', attrs={"class": "details"}).children:
            field_str = str(field)
            field_str = field_str.replace("\n", "")
            print(field_str)
            if "#icon-contract" in field_str:
                m = findall(r"svg>(\w|\s)+<\/li>", field_str)
            # print(field.string)
        sanitiser = Sanitizer()
        content = sanitiser.sanitize(content)
        return {"post_details": content, "fields": {}}
    except:
        raise InvalidUserInput(
            description="Couldn't find details for that job")
Exemple #16
0
def get_company_details(company):
    """
        Params: 
            - company (str)
        Returns:
            - company_description (str)
    """
    wiki_wiki = Wikipedia('en')

    try:
        # try different methods for searching  for the company until something good is returned
        page = wiki_wiki.page(company + " (company)")

        if not page.exists():
            page = wiki_wiki.page(company)
    except Exception as err:
        printColoured(err, colour="red")
        raise InvalidUserInput(
            description="Connection timed out. Please try again later")

    company_data = page.text
    company_description = company_data.split("\n")[0]
    return company_description
Exemple #17
0
    def get(self):
        """
            Fetches user activity data for each date.
            Preprocesses it so that each date has a list of activities the user did.
            This makes it easy for the frontend to render graphically

            Parameters:
                - user_id
                - board_id
                - start time
                - end time
        """
        printColoured(" * Getting user activity stats", colour="yellow")
        request_params = dict(request.args)
        user_id = request_params["user_id"]
        board_id = request_params["board_id"]

        stats = fetch_stats(user_id, board_id)

        # Sort timestamps into ascending order
        stats.sort(key=lambda x: x["timestamp"])
        start_date = datetime.fromtimestamp(int(request_params["start_time"]))
        end_date = datetime.fromtimestamp(int(request_params["end_time"]))

        delta = end_date - start_date
        if (delta.days < 0):
            raise InvalidUserInput(
                description=
                "Invalid time range. Check that the start time is after end time"
            )

        date_list = {}

        # METHOD 1 - iterating through the entire stats array for each day
        #            takes longer but more confident that it is more accurate
        for i in range(delta.days + 2):
            day = start_date + timedelta(days=i)
            day = day.strftime('%d/%m/%Y')
            date_list[day] = []
            for j in range(len(stats)):
                curr_day = datetime.fromtimestamp(
                    stats[j]['timestamp']).strftime('%d/%m/%Y')
                if curr_day != day:
                    continue
                date_list[day].append((stats[j]['activity']))
                date_list[day].sort()

        # METHOD 2 - stop iterating through the stats array when dates no longer match
        #            keeps track of last position in stats array so no need to iterate through days that have already been matched
        #            takes shorter time but might be less accurate
        '''for i in range(delta.days + 2):
            day = (start_date + timedelta(days = i)).strftime('%d/%m/%Y')
            k = 0
            for j in range(k, len(stats)):
                curr_day = datetime.fromtimestamp(stats[j]['timestamp']).strftime('%d/%m/%Y')
                if curr_day < day:
                    continue
                elif curr_day > day:
                    k = j
                    break

                if day not in date_list.keys():
                    activity_list = []

                activity_list.append((stats[j]['activity']))
                activity_list.sort()
                date_list[day] = activity_list'''

        # For each day between start time and end time,
        return date_list