<commit_before>/**
 * WarfaceBot, a blind XMPP client for Warface (FPS)
 * Copyright (C) 2015, 2016 <NAME> <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <wb_tools.h>
#include <wb_stream.h>
#include <wb_session.h>
#include <wb_xmpp.h>
#include <wb_xmpp_wf.h>
#include <wb_game.h>
#include <wb_mission.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct cb_args
{
    char *channel;
    f_join_channel_cb cb;
    void *args;
};

static void xmpp_iq_join_channel_cb(const char *msg,
                                    enum xmpp_msg_type type,
                                    void *args)
{
    /* Answer
      <iq from='masterserver@warface/pve_12' to='xxxxxx@warface/GameClient' type='result'>
       <query xmlns='urn:cryonline:k01'>
        <data query_name='join_channel' compressedData='...' originalSize='13480'/>
       </query>
      </iq>
     */

    struct cb_args *a = (struct cb_args *) args;

    if (type & XMPP_TYPE_ERROR)
    {
        fprintf(stderr, "Failed to join channel\nReason: ");

        int code = get_info_int(msg, "code='", "'", NULL);
        int custom_code = get_info_int(msg, "custom_code='", "'", NULL);

        switch (code)
        {
            case 1006:
                fprintf(stderr, "QoS limit reached\n");
                break;
            case 503:
                fprintf(stderr, "Invalid channel (%s)\n", a->channel);
                break;
            case 8:
                switch (custom_code)
                {
                    case 0:
                        fprintf(stderr, "Invalid token (%s) or userid (%s)\n",
                                session.online.active_token,
                                session.online.id);
                        break;
                    case 1:
                        fprintf(stderr, "Invalid profile_id (%s)\n",
                                session.profile.id);
                        break;
                    case 2:
                        fprintf(stderr, "Game version mismatch (%s)\n",
                                game_version_get());
                        break;
                    case 3:
                        fprintf(stderr, "Banned\n");
                        break;
                    case 5:
                        fprintf(stderr, "Rank restricted\n");
                        break;
                    default:
                        fprintf(stderr, "Unknown code (%d)\n", custom_code);
                        break;
                }
                break;
            default:
                fprintf(stderr, "Unknown\n");
                break;
        }
    }
    else
    {
        char *data = wf_get_query_content(msg);

        /* Leave previous room if any */
        xmpp_iq_gameroom_leave();

        if (data != NULL)
        {
            char is_join_channel = strstr(data, "<join_channel") != NULL;

            /* Update own channel */
            if (a->channel != NULL)
            {
                free(session.online.channel);
                session.online.channel = strdup(a->channel);
            }

            /* Update experience */
            {
                unsigned int experience =
                    get_info_int(data, "experience='", "'", "EXPERIENCE");

                if (experience > 0)
                    session.profile.experience = experience;
            }

            /* Update PvP rating points */
            {
                unsigned int rating_points =
                    get_info_int(data, "pvp_rating_points='", "'", NULL);

                if (rating_points > 0)
                    session.profile.stats.pvp.rating_points = rating_points;
            }

            /* Update banner */
            {
                unsigned int banner_badge =
                    get_info_int(data, "banner_badge='", "'", NULL);
                unsigned int banner_mark =
                    get_info_int(data, "banner_mark='", "'", NULL);
                unsigned int banner_stripe =
                    get_info_int(data, "banner_stripe='", "'", NULL);

                if (banner_badge > 0)
                    session.profile.banner.badge = banner_badge;
                if (banner_mark > 0)
                    session.profile.banner.mark = banner_mark;
                if (banner_stripe > 0)
                    session.profile.banner.stripe = banner_stripe;
            }

            if (is_join_channel)
            {
                /* Update money */
                unsigned int game_money =
                    get_info_int(data, "game_money='", "'", "MONEY");
                unsigned int crown_money =
                    get_info_int(data, "crown_money='", "'", "CROWNS");
                unsigned int cry_money =
                    get_info_int(data, "cry_money='", "'", "KREDITS");

                if (game_money > 0)
                    session.profile.money.game = game_money;
                if (crown_money > 0)
                    session.profile.money.crown = crown_money;
                if (cry_money > 0)
                    session.profile.money.cry = cry_money;
            }

            /* Fetch currently equipped weapon */
            {
                const char *m = data;
                enum e_class class = get_info_int(data, "current_class='", "'", NULL);

                while ((m = strstr(m, "<item")))
                {
                    char *item = get_info(m, "<item", "/>", NULL);
                    int equipped = get_info_int(item, "equipped='", "'", NULL);
                    int slot = get_info_int(item, "slot='", "'", NULL);

                    if (equipped && (slot == (1 << class)))
                    {
                        char *name = get_info(item, "name='", "'", NULL);
                        free(session.profile.primary_weapon);
                        session.profile.primary_weapon = name;
                    }

                    free(item);
                    ++m;
                }
            }

            /* Fetch unlocked items */
            {
                unsigned int unlocked_items = 0;
                const char *m = data;

                while ((m = strstr(m, "<unlocked_item")))
                {
                    ++unlocked_items;
                    ++m;
                }

                if (unlocked_items > 0)
                    session.profile.stats.items_unlocked = unlocked_items;
            }

            /* Fetch notifications */
            {
                const char *m = data;

                while ((m = strstr(m, "<notif")))<commit_msg>Fix primary weapon display when class_id is not 0<commit_after>/**
 * WarfaceBot, a blind XMPP client for Warface (FPS)
 * Copyright (C) 2015, 2016 <NAME> <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <wb_tools.h>
#include <wb_stream.h>
#include <wb_session.h>
#include <wb_xmpp.h>
#include <wb_xmpp_wf.h>
#include <wb_game.h>
#include <wb_mission.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct cb_args
{
    char *channel;
    f_join_channel_cb cb;
    void *args;
};

static void xmpp_iq_join_channel_cb(const char *msg,
                                    enum xmpp_msg_type type,
                                    void *args)
{
    /* Answer
      <iq from='masterserver@warface/pve_12' to='xxxxxx@warface/GameClient' type='result'>
       <query xmlns='urn:cryonline:k01'>
        <data query_name='join_channel' compressedData='...' originalSize='13480'/>
       </query>
      </iq>
     */

    struct cb_args *a = (struct cb_args *) args;

    if (type & XMPP_TYPE_ERROR)
    {
        fprintf(stderr, "Failed to join channel\nReason: ");

        int code = get_info_int(msg, "code='", "'", NULL);
        int custom_code = get_info_int(msg, "custom_code='", "'", NULL);

        switch (code)
        {
            case 1006:
                fprintf(stderr, "QoS limit reached\n");
                break;
            case 503:
                fprintf(stderr, "Invalid channel (%s)\n", a->channel);
                break;
            case 8:
                switch (custom_code)
                {
                    case 0:
                        fprintf(stderr, "Invalid token (%s) or userid (%s)\n",
                                session.online.active_token,
                                session.online.id);
                        break;
                    case 1:
                        fprintf(stderr, "Invalid profile_id (%s)\n",
                                session.profile.id);
                        break;
                    case 2:
                        fprintf(stderr, "Game version mismatch (%s)\n",
                                game_version_get());
                        break;
                    case 3:
                        fprintf(stderr, "Banned\n");
                        break;
                    case 5:
                        fprintf(stderr, "Rank restricted\n");
                        break;
                    default:
                        fprintf(stderr, "Unknown code (%d)\n", custom_code);
                        break;
                }
                break;
            default:
                fprintf(stderr, "Unknown\n");
                break;
        }
    }
    else
    {
        char *data = wf_get_query_content(msg);

        /* Leave previous room if any */
        xmpp_iq_gameroom_leave();

        if (data != NULL)
        {
            char is_join_channel = strstr(data, "<join_channel") != NULL;

            /* Update own channel */
            if (a->channel != NULL)
            {
                free(session.online.channel);
                session.online.channel = strdup(a->channel);
            }

            /* Update experience */
            {
                unsigned int experience =
                    get_info_int(data, "experience='", "'", "EXPERIENCE");

                if (experience > 0)
                    session.profile.experience = experience;
            }

            /* Update PvP rating points */
            {
                unsigned int rating_points =
                    get_info_int(data, "pvp_rating_points='", "'", NULL);

                if (rating_points > 0)
                    session.profile.stats.pvp.rating_points = rating_points;
            }

            /* Update banner */
            {
                unsigned int banner_badge =
                    get_info_int(data, "banner_badge='", "'", NULL);
                unsigned int banner_mark =
                    get_info_int(data, "banner_mark='", "'", NULL);
                unsigned int banner_stripe =
                    get_info_int(data, "banner_stripe='", "'", NULL);

                if (banner_badge > 0)
                    session.profile.banner.badge = banner_badge;
                if (banner_mark > 0)
                    session.profile.banner.mark = banner_mark;
                if (banner_stripe > 0)
                    session.profile.banner.stripe = banner_stripe;
            }

            if (is_join_channel)
            {
                /* Update money */
                unsigned int game_money =
                    get_info_int(data, "game_money='", "'", "MONEY");
                unsigned int crown_money =
                    get_info_int(data, "crown_money='", "'", "CROWNS");
                unsigned int cry_money =
                    get_info_int(data, "cry_money='", "'", "KREDITS");

                if (game_money > 0)
                    session.profile.money.game = game_money;
                if (crown_money > 0)
                    session.profile.money.crown = crown_money;
                if (cry_money > 0)
                    session.profile.money.cry = cry_money;
            }

            /* Fetch currently equipped weapon */
            {
                const char *m = data;
                enum e_class class = get_info_int(data, "current_class='", "'", NULL);

                while ((m = strstr(m, "<item")))
                {
                    char *item = get_info(m, "<item", "/>", NULL);
                    int equipped = get_info_int(item, "equipped='", "'", NULL);
                    int slot = get_info_int(item, "slot='", "'", NULL);

                    if (equipped && (slot == (1 << (5 * class))))
                    {
                        char *name = get_info(item, "name='", "'", NULL);
                        free(session.profile.primary_weapon);
                        session.profile.primary_weapon = name;
                    }

                    free(item);
                    ++m;
                }
            }

            /* Fetch unlocked items */
            {
                unsigned int unlocked_items = 0;
                const char *m = data;

                while ((m = strstr(m, "<unlocked_item")))
                {
                    ++unlocked_items;
                    ++m;
                }

                if (unlocked_items > 0)
                    session.profile.stats.items_unlocked = unlocked_items;
            }

            /* Fetch notifications */
            {
                const char *m = data;

                while ((m = strstr(m, "<notif")))
{'fraction_non_alphanumeric': 0.10759318276292087, 'fraction_numerical': 0.005958154357766385, 'mean_word_length': 1.2757370329497084, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2124113', 'n_tokens_mistral': 4083, 'n_tokens_neox': 3707, 'n_words': 950}