Exemple #1
0
def sync_user_profile_with_wk(user):
    '''
    Hits the WK api with user information in order to synchronize user metadata such as level and gravatar information.

    :param user: The user to sync their profile with WK.
    :return: boolean indicating the success of the API call.
    '''
    api_string = build_user_information_api_string(user.profile.api_key)

    try:
        json_data = make_api_call(api_string)
    except exceptions.InvalidWaniKaniKey:
        user.profile.api_valid = False
        user.profile.save()
        return False

    user_info = json_data["user_information"]
    user.profile.title = user_info["title"]
    user.profile.join_date = datetime.utcfromtimestamp(user_info["creation_date"])
    user.profile.topics_count = user_info["topics_count"]
    user.profile.posts_count = user_info["posts_count"]
    user.profile.about = user_info["about"]
    user.profile.set_website(user_info["website"])
    user.profile.set_twitter_account(user_info["twitter"])
    user.profile.gravatar = user_info["gravatar"]
    user.profile.last_wanikani_sync_date = timezone.now()
    user.profile.api_valid = True
    if user.profile.follow_me:
        user.profile.unlocked_levels.get_or_create(level=user_info["level"])
        user.profile.handle_wanikani_level_change(user_info["level"])

    user.profile.save()

    logger.info("Synced {}'s Profile.".format(user.username))
    return True
Exemple #2
0
def sync_user_profile_with_wk(user):
    """
    Hits the WK api with user information in order to synchronize user metadata such as level and gravatar information.

    :param user: The user to sync their profile with WK.
    :return: boolean indicating the success of the API call.
    """
    api_string = build_user_information_api_string(user.profile.api_key)

    try:
        json_data = make_api_call(api_string)
    except exceptions.InvalidWaniKaniKey:
        user.profile.api_valid = False
        user.profile.save()
        return False

    user_info = json_data["user_information"]
    user.profile.title = user_info["title"]
    user.profile.join_date = datetime.utcfromtimestamp(user_info["creation_date"])
    user.profile.topics_count = user_info["topics_count"]
    user.profile.posts_count = user_info["posts_count"]
    user.profile.about = user_info["about"]
    user.profile.set_website(user_info["website"])
    user.profile.set_twitter_account(user_info["twitter"])
    user.profile.gravatar = user_info["gravatar"]
    user.profile.last_wanikani_sync_date = timezone.now()
    user.profile.api_valid = True
    if user.profile.follow_me:
        user.profile.unlocked_levels.get_or_create(level=user_info["level"])
        user.profile.handle_wanikani_level_change(user_info["level"])

    user.profile.save()

    logger.info("Synced {}'s Profile.".format(user.username))
    return True
Exemple #3
0
def one_time_merge_level(level, user=None):
    api_call = "https://www.wanikani.com/api/user/{}/vocabulary/{}".format(
        constants.API_KEY, level)
    response = make_api_call(api_call)
    vocab_list = response['requested_information']
    print("Vocab found:{}".format(len(vocab_list)))

    for vocabulary_json in vocab_list:
        print("**************************************************************")
        print("Analyzing vocab with kanji:[{}]\tCanonical meaning is:[{}]".
              format(vocabulary_json['character'], vocabulary_json['meaning']))
        found_vocabulary = Vocabulary.objects.filter(
            readings__character=vocabulary_json['character'])
        print("found [{}] vocabulary on the server with kanji [{}]".format(
            found_vocabulary.count(), vocabulary_json['character']))
        if found_vocabulary.count(
        ) == 1 and found_vocabulary[0].meaning == vocabulary_json['meaning']:
            print(
                "No conflict found. Precisely 1 vocab on server, and meaning matches."
            )
        elif found_vocabulary.count() > 1:
            print(
                "Conflict found. Precisely [{}] vocab on server for meaning [{}]."
                .format(found_vocabulary.count(), vocabulary_json['meaning']))
            handle_merger(vocabulary_json, found_vocabulary)
        elif found_vocabulary.count() == 0:
            create_new_vocabulary(vocabulary_json)
        else:
            print("No conflict, but meaning has changed. Changing meaning!")
            to_be_edited = found_vocabulary[0]
            to_be_edited.meaning = vocabulary_json['meaning']
            to_be_edited.save()
Exemple #4
0
def sync_unlocked_vocab_with_wk(user):
    if user.profile.unlocked_levels_list():
        pages = get_level_pages(user.profile.unlocked_levels_list())
        new_review_count = new_synonym_count = 0
        for page in pages:
            request_string = build_API_sync_string_for_user_for_levels(user, page)
            logger.info(
                "Creating sync string for user {}: {}".format(
                    user.username, user.profile.api_key
                )
            )
            try:
                response = make_api_call(request_string)
                current_page_review_count, current_page_synonym_count = process_vocabulary_response_for_user(
                    user, response
                )
                new_review_count += current_page_review_count
                new_synonym_count += current_page_synonym_count
            except exceptions.InvalidWaniKaniKey:
                user.profile.api_valid = False
                user.profile.save()
            except exceptions.WanikaniAPIException as e:
                logger.error(
                    "Couldn't sync recent vocab for {}".format(user.username), e
                )
        return new_review_count, new_synonym_count
    else:
        return 0, 0
Exemple #5
0
    def get_wanikani_level(self):
        api_string = self.build_user_information_api_string(
            self.profile.api_key)

        json_data = make_api_call(api_string)
        user_info = json_data["user_information"]
        return user_info["level"]
Exemple #6
0
 def sync_recent_unlocked_vocab(self):
     if self.profile.unlocked_levels_list():
         levels = [
             level for level in range(self.profile.level -
                                      2, self.profile.level + 1)
             if level in self.profile.unlocked_levels_list()
         ]
         if levels:
             logger.info(
                 f"Target levels: {','.join([str(level) for level in levels])}"
             )
             request_string = self.build_API_sync_string_for_levels(levels)
             try:
                 logger.info(f"About to make recent vocab sync request")
                 json_data = make_api_call(request_string)
                 new_review_count, new_synonym_count = self.process_vocabulary_response_for_user_classic(
                     json_data)
                 logger.info(
                     f"Successfully did a recent sync for {self.profile.user.username}"
                 )
                 return new_review_count, new_synonym_count
             except exceptions.InvalidWaniKaniKey:
                 self.profile.api_valid = False
                 self.profile.save()
             except exceptions.WanikaniAPIException as e:
                 logger.warning(
                     f"Couldn't sync recent vocab for {self.profile.user.username}:, {e}"
                 )
     return 0, 0
     pass
Exemple #7
0
def get_wanikani_level_by_api_key(api_key):
    api_string = "https://www.wanikani.com/api/user/{}/user-information".format(
        api_key)
    response = make_api_call(api_string)
    user_info = response["user_information"]
    level = user_info["level"]
    return level
Exemple #8
0
def sync_unlocked_vocab_with_wk(user):
    if user.profile.unlocked_levels_list():
        pages = get_level_pages(user.profile.unlocked_levels_list())
        new_review_count = new_synonym_count = 0
        for page in pages:
            request_string = build_API_sync_string_for_user_for_levels(
                user, page)
            logger.info("Creating sync string for user {}: {}".format(
                user.username, user.profile.api_key))
            try:
                response = make_api_call(request_string)
                current_page_review_count, current_page_synonym_count = process_vocabulary_response_for_user(
                    user, response)
                new_review_count += current_page_review_count
                new_synonym_count += current_page_synonym_count
            except exceptions.InvalidWaniKaniKey:
                user.profile.api_valid = False
                user.profile.save()
            except exceptions.WanikaniAPIException as e:
                logger.error(
                    "Couldn't sync recent vocab for {}".format(user.username),
                    e)
        return new_review_count, new_synonym_count
    else:
        return 0, 0
Exemple #9
0
def sync_unlocked_vocab_with_wk(user):
    if user.profile.unlocked_levels_list():
        request_string = build_API_sync_string_for_user(user)
        response = make_api_call(request_string)
        new_review_count, new_synonym_count = process_vocabulary_response_for_user(
            user, response)
        return new_review_count, new_synonym_count
    else:
        return 0, 0
Exemple #10
0
def unlock_eligible_vocab_from_levels(user, levels):
    """
    I don't like duplicating code like this, but its for the purpose of reducing API call load on WaniKani. It's a
    hassle if the user caps out.
    :param user: user to add vocab to. :param levels: requested level unlock. This can
    also be a list. :return: unlocked count, locked count
    """

    api_call_string = build_API_sync_string_for_user_for_levels(user, levels)
    response = make_api_call(api_call_string)
    unlocked_this_request, total_unlocked, locked = process_vocabulary_response_for_unlock(user, response)
    return unlocked_this_request, total_unlocked, locked
Exemple #11
0
    def sync_user_profile_with_wk(self):
        """
        Hits the WK api in order to synchronize user metadata such as level and gravatar information.

        :param user: The user to sync their profile with WK.
        :return: boolean indicating the success of the API call.
        """
        api_string = self.build_user_information_api_string(
            self.profile.api_key)
        logger.info(
            f"About to attempt profile update for {self.profile.user.username}: {api_string} "
        )

        try:
            json_data = make_api_call(api_string)
        except exceptions.InvalidWaniKaniKey:
            self.profile.api_valid = False
            self.profile.save()
            return False

        logger.info(
            f"Successfully fetched profile information for {self.profile.user.username}"
        )
        user_info = json_data["user_information"]
        self.profile.title = user_info["title"]
        self.profile.join_date = datetime.utcfromtimestamp(
            user_info["creation_date"])
        self.profile.topics_count = user_info["topics_count"]
        self.profile.posts_count = user_info["posts_count"]
        self.profile.about = user_info["about"]
        self.profile.set_website(user_info["website"])
        self.profile.set_twitter_account(user_info["twitter"])
        self.profile.gravatar = user_info["gravatar"]
        self.profile.last_wanikani_sync_date = timezone.now()
        self.profile.api_valid = True

        if self.profile.follow_me:
            self.profile.unlocked_levels.get_or_create(
                level=user_info["level"])
            self.profile.handle_wanikani_level_change(user_info["level"])

        if self._wanikani_has_lapsed(user_info["level"]):
            logger.info(
                f"Looks like {self.profile.user.username}'s Wanikani account has lapsed, we are hibernating their syncing"
            )
            self.profile.has_lapsed_wanikani = True

        self.profile.save()

        logger.info(f"Synced {self.profile.user.username}'s Profile.")

        return True
Exemple #12
0
 def unlock_vocab(self, levels):
     """
     I don't like duplicating code like this, but its for the purpose of reducing API call load on WaniKani. It's a
     hassle if the user caps out.
     :param user: user to add vocab to. :param levels: requested level unlock. This can
     also be a list. :return: unlocked count, locked count
     """
     logger.info(f"About to begin level unlock ")
     api_call_string = self.build_API_sync_string_for_levels(levels)
     response = make_api_call(api_call_string)
     unlocked_this_request, total_unlocked, locked = self.process_vocabulary_response_for_unlock(
         response)
     return unlocked_this_request, total_unlocked, locked
Exemple #13
0
    def pull_user_synonyms_by_level(self, level):
        """
        Retrieves vocabulary list from the WK API, specifically searching to pull in synonyms.

        :param user: User to pull WK synonyms or
        :param level: The level for synonyms that should be pulled
        :return: None
        """
        request_string = self.build_API_sync_string_for_user_for_levels(level)
        try:
            logger.info(f"Pulling down user synonyms: {request_string}")
            json_data = make_api_call(request_string)
            vocabulary_list = json_data["requested_information"]
            for vocabulary in vocabulary_list:
                meaning = vocabulary["meaning"]
                if (vocabulary["user_specific"]
                        and vocabulary["user_specific"]["user_synonyms"]):
                    try:
                        review = UserSpecific.objects.get(
                            user=self.profile.user,
                            vocabulary__meaning=meaning)
                        for synonym in vocabulary["user_specific"][
                                "user_synonyms"]:
                            review.meaning_synonyms.get_or_create(text=synonym)
                        review.save()
                    except UserSpecific.DoesNotExist as e:
                        logger.error(
                            f"Couldn't pull review during a synonym sync: {e}")
                    except KeyError:
                        logger.error(
                            f"No user_specific or synonyms?: {json_data}")
                    except UserSpecific.MultipleObjectsReturned:
                        reviews = UserSpecific.objects.filter(
                            user=self.profile.user,
                            vocabulary__meaning=meaning)
                        for review in reviews:
                            logger.error(
                                f"Found something janky! Multiple reviews under 1 vocab meaning?!?: {review}"
                            )

        except exceptions.InvalidWaniKaniKey as e:
            logger.warning("Invalid api key! {}", e)
            self.profile.api_valid = False
            self.profile.save()
        except exceptions.WanikaniAPIException as e:
            logger.warning(
                f"Couldnt pull user synonyms for {self.profile.user.username}",
                e,
            )
Exemple #14
0
def repopulate():
    '''
    A task that uses my personal API key in order to re-sync the database. Koichi often decides to switch things around
    on a level-per-level basis, or add synonyms, or change which readings are allowed. This method attempts to synchronize
    our data sets.

    :return:
    '''
    url = "https://www.wanikani.com/api/user/" + constants.API_KEY + "/vocabulary/{}"
    logger.info("Staring DB Repopulation from WaniKani")
    for level in range(constants.LEVEL_MIN, constants.LEVEL_MAX + 1):
        json_data = make_api_call(url.format(level))
        vocabulary_list = json_data['requested_information']
        for vocabulary in vocabulary_list:
            sync_single_vocabulary_item_by_json(vocabulary)
Exemple #15
0
def sync_recent_unlocked_vocab_with_wk(user):
    if user.profile.unlocked_levels_list():
        levels = [
            level
            for level in range(user.profile.level - 2, user.profile.level + 1)
            if level in user.profile.unlocked_levels_list()
        ]
        if levels:
            request_string = build_API_sync_string_for_user_for_levels(
                user, levels)
            json_data = make_api_call(request_string)
            new_review_count, new_synonym_count = process_vocabulary_response_for_user(
                user, json_data)
            return new_review_count, new_synonym_count
    return 0, 0
Exemple #16
0
def repopulate():
    """
    A task that uses my personal API key in order to re-sync the database. Koichi often decides to switch things around
    on a level-per-level basis, or add synonyms, or change which readings are allowed. This method attempts to synchronize
    our data sets.

    :return:
    """
    url = "https://www.wanikani.com/api/user/" + constants.API_KEY + "/vocabulary/{}"
    logger.info("Starting DB Repopulation from WaniKani")
    for level in range(constants.LEVEL_MIN, constants.LEVEL_MAX + 1):
        json_data = make_api_call(url.format(level))
        vocabulary_list = json_data["requested_information"]
        for vocabulary in vocabulary_list:
            import_vocabulary_from_json(vocabulary)
Exemple #17
0
def sync_recent_unlocked_vocab_with_wk(user):
    if user.profile.unlocked_levels_list():
        levels = [level for level in range(user.profile.level - 2, user.profile.level + 1) if
                  level in user.profile.unlocked_levels_list()]
        if levels:
            request_string = build_API_sync_string_for_user_for_levels(user, levels)
            try:
                json_data = make_api_call(request_string)
                new_review_count, new_synonym_count = process_vocabulary_response_for_user(user, json_data)
                return new_review_count, new_synonym_count
            except exceptions.InvalidWaniKaniKey:
                user.profile.api_valid = False
                user.profile.save()
            except exceptions.WanikaniAPIException as e:
                logger.warn("Couldn't sync recent vocab for {}".format(user.username), e)
    return 0, 0
Exemple #18
0
def pull_user_synonyms_by_level(user, level):
    """
    Retrieves vocabulary list from the WK API, specifically searching to pull in synonyms.

    :param user: User to pull WK synonyms or
    :param level: The level for synonyms that should be pulled
    :return: None
    """
    request_string = build_API_sync_string_for_user_for_levels(user, level)
    try:
        json_data = make_api_call(request_string)
        vocabulary_list = json_data["requested_information"]
        for vocabulary in vocabulary_list:
            meaning = vocabulary["meaning"]
            if (
                vocabulary["user_specific"]
                and vocabulary["user_specific"]["user_synonyms"]
            ):
                try:
                    review = UserSpecific.objects.get(
                        user=user, vocabulary__meaning=meaning
                    )
                    for synonym in vocabulary["user_specific"]["user_synonyms"]:
                        review.meaning_synonyms.get_or_create(text=synonym)
                    review.save()
                except UserSpecific.DoesNotExist as e:
                    logger.error(
                        "Couldn't pull review during a synonym sync: {}".format(e)
                    )
                except KeyError as e:
                    logger.error("No user_specific or synonyms?: {}".format(json_data))
                except UserSpecific.MultipleObjectsReturned:
                    reviews = UserSpecific.objects.filter(
                        user=user, vocabulary__meaning=meaning
                    )
                    for review in reviews:
                        logger.error(
                            "Found something janky! Multiple reviews under 1 vocab meaning?!?: {}".format(
                                review
                            )
                        )

    except exceptions.InvalidWaniKaniKey:
        user.profile.api_valid = False
        user.profile.save()
    except exceptions.WanikaniAPIException as e:
        logger.warning("Couldnt pull user synonyms for {}".format(user.username), e)
Exemple #19
0
def sync_unlocked_vocab_with_wk(user):
    if user.profile.unlocked_levels_list():
        pages = get_level_pages(user.profile.unlocked_levels_list())
        new_review_count = new_synonym_count = 0
        for page in pages:
            request_string = build_API_sync_string_for_user_for_levels(
                user, page)
            logger.info("Creating sync string for user {}: {}".format(
                user.username, user.profile.api_key))
            response = make_api_call(request_string)
            current_page_review_count, current_page_synonym_count = process_vocabulary_response_for_user(
                user, response)
            new_review_count += current_page_review_count
            new_synonym_count += current_page_synonym_count
        return new_review_count, new_synonym_count
    else:
        return 0, 0
Exemple #20
0
def one_time_merge_level(level, user=None):
    api_call = "https://www.wanikani.com/api/user/{}/vocabulary/{}".format(
        constants.API_KEY, level
    )
    response = make_api_call(api_call)
    vocab_list = response["requested_information"]
    print("Vocab found:{}".format(len(vocab_list)))

    for vocabulary_json in vocab_list:
        print("**************************************************************")
        print(
            "Analyzing vocab with kanji:[{}]\tCanonical meaning is:[{}]".format(
                vocabulary_json["character"], vocabulary_json["meaning"]
            )
        )
        found_vocabulary = Vocabulary.objects.filter(
            readings__character=vocabulary_json["character"]
        )
        print(
            "found [{}] vocabulary on the server with kanji [{}]".format(
                found_vocabulary.count(), vocabulary_json["character"]
            )
        )
        if (
            found_vocabulary.count() == 1
            and found_vocabulary[0].meaning == vocabulary_json["meaning"]
        ):
            print(
                "No conflict found. Precisely 1 vocab on server, and meaning matches."
            )
        elif found_vocabulary.count() > 1:
            print(
                "Conflict found. Precisely [{}] vocab on server for meaning [{}].".format(
                    found_vocabulary.count(), vocabulary_json["meaning"]
                )
            )
            handle_merger(vocabulary_json, found_vocabulary)
        elif found_vocabulary.count() == 0:
            create_new_vocabulary(vocabulary_json)
        else:
            print("No conflict, but meaning has changed. Changing meaning!")
            to_be_edited = found_vocabulary[0]
            to_be_edited.meaning = vocabulary_json["meaning"]
            to_be_edited.save()
Exemple #21
0
def pull_user_synonyms_by_level(user, level):
    '''
    Retrieves vocabulary list from the WK API, specifically searching to pull in synonyms.

    :param user: User to pull WK synonyms or
    :param level: The level for synonyms that should be pulled
    :return: None
    '''
    request_string = build_API_sync_string_for_user_for_levels(user, level)
    try:
        json_data = make_api_call(request_string)
        vocabulary_list = json_data['requested_information']
        for vocabulary in vocabulary_list:
            meaning = vocabulary["meaning"]
            if vocabulary['user_specific'] and vocabulary['user_specific'][
                    'user_synonyms']:
                try:
                    review = UserSpecific.objects.get(
                        user=user, vocabulary__meaning=meaning)
                    for synonym in vocabulary['user_specific'][
                            'user_synonyms']:
                        review.meaning_synonyms.get_or_create(text=synonym)
                    review.save()
                except UserSpecific.DoesNotExist as e:
                    logger.error(
                        "Couldn't pull review during a synonym sync: {}".
                        format(e))
                except KeyError as e:
                    logger.error(
                        "No user_specific or synonyms?: {}".format(json_data))
                except UserSpecific.MultipleObjectsReturned:
                    reviews = UserSpecific.objects.filter(
                        user=user, vocabulary__meaning=meaning)
                    for review in reviews:
                        logger.error(
                            "Found something janky! Multiple reviews under 1 vocab meaning?!?: {}"
                            .format(review))

    except exceptions.InvalidWaniKaniKey:
        user.profile.api_valid = False
        user.profile.save()
    except exceptions.WanikaniAPIException as e:
        logger.warning(
            "Couldnt pull user synonyms for {}".format(user.username), e)
Exemple #22
0
def unlock_eligible_vocab_from_levels(user, levels):
    """
    I don't like duplicating code like this, but its for the purpose of reducing API call load on WaniKani. It's a
    hassle if the user caps out.
    :param user: user to add vocab to. :param levels: requested level unlock. This can
    also be a list. :return: unlocked count, locked count
    """

    api_call_string = build_API_sync_string_for_user_for_levels(user, levels)

    try:
        response = make_api_call(api_call_string)
        unlocked_this_request, total_unlocked, locked = process_vocabulary_response_for_unlock(user, response)
        return unlocked_this_request, total_unlocked, locked
    except exceptions.InvalidWaniKaniKey:
        logger.error("Invalid key found for user {}".format(user.username))
        user.profile.api_valid = False
        user.profile.save()
    except exceptions.WanikaniAPIException as e:
        logger.error("Non-invalid key error found during API call. ", e)
Exemple #23
0
def sync_recent_unlocked_vocab_with_wk(user):
    if user.profile.unlocked_levels_list():
        levels = [
            level
            for level in range(user.profile.level - 2, user.profile.level + 1)
            if level in user.profile.unlocked_levels_list()
        ]
        if levels:
            request_string = build_API_sync_string_for_user_for_levels(user, levels)
            try:
                json_data = make_api_call(request_string)
                new_review_count, new_synonym_count = process_vocabulary_response_for_user(
                    user, json_data
                )
                return new_review_count, new_synonym_count
            except exceptions.InvalidWaniKaniKey:
                user.profile.api_valid = False
                user.profile.save()
            except exceptions.WanikaniAPIException as e:
                logger.warn(
                    "Couldn't sync recent vocab for {}".format(user.username), e
                )
    return 0, 0
Exemple #24
0
 def sync_unlocked_vocab(self):
     if self.profile.unlocked_levels_list():
         new_review_count = new_synonym_count = 0
         request_string = self.build_API_sync_string_for_levels(
             self.profile.unlocked_levels_list())
         logger.info(
             f"Creating sync string for user {self.profile.user.username}: {request_string}"
         )
         try:
             response = make_api_call(request_string)
             current_page_review_count, current_page_synonym_count = self.process_vocabulary_response_for_user_classic(
                 response)
             new_review_count += current_page_review_count
             new_synonym_count += current_page_synonym_count
         except exceptions.InvalidWaniKaniKey:
             self.profile.api_valid = False
             self.profile.save()
         except exceptions.WanikaniAPIException as e:
             logger.warning(
                 f"Couldn't sync vocab for {self.profile.user.username}: {e}"
             )
         return new_review_count, new_synonym_count
     else:
         return 0, 0
Exemple #25
0
def get_wanikani_level_by_api_key(api_key):
    api_string = "https://www.wanikani.com/api/user/{}/user-information".format(api_key)
    response = make_api_call(api_string)
    user_info = response["user_information"]
    level = user_info["level"]
    return level