Home Reference Source

js/models/StackExchange.js

import Data from '~/models/Data';
import Request from '~/models/Request/Request';

/**
 * Talks to SE API
 */
export default class StackExchangege {
    /**
     * Logs in and gets auth key
     * @return {string}
     */
    static loginAuthKey() {
        return new Promise((resolve, reject) => {
            const authWindow = window.open(
                `https://stackexchange.com/oauth?` +
                `client_id=${Data.shared.envValueForKey('SE_CLIENT_ID')}` +
                `&scope=` +
                `&state=${btoa(JSON.stringify({
                    provider: 'se',
                    clientOnly: true
                }))}` +
                `&redirect_uri=${Data.shared.envValueForKey('OAUTH_CALLBACK')}`,
                'Axtell authentication for Stack Exchange',
                'width=800,height=800,toolbar=0,menubar=0'
            );

            window.addEventListener('message', (event) => {
                // The response
                if (event.source === authWindow) {
                    const data = event.data;
                    if (data.success === true) {
                        event.source.postMessage({ received: true }, '*');
                        resolve(data.authKey);
                    } else {
                        reject();
                    }
                }
            });
        });
    }

    /**
     * Authorizes to SE object
     * @return {StackExchange}
     */
    static async authorize() {
        const authKey = await this.loginAuthKey();
        return new this(authKey);
    }

    constructor(authKey) {
        /** @private */
        this.authKey = authKey;
    }

    apiRequest(path, params) {
        return new Request({
            host: 'https://api.stackexchange.com',
            path: path,
            params: {
                ...params,
                key: Data.shared.envValueForKey('SE_KEY'),
                access_token: this.authKey
            }
        });
    }

    async pagingApiRequest(path, params) {
        let allItems = [],
            page = 1,
            hasMore;

        do {
            let { items, has_more } = await this.apiRequest(path, {
                ...params,
                page: page++
            }).run();

            hasMore = has_more;

            for (let i = 0; i < items.length; i++) {
                allItems.push(items[i]);
            }
        } while(hasMore);

        return allItems;
    }

    /**
     * Gets the posts
     */
    async getQuestions() {
        const results = await this.pagingApiRequest('/2.2/me/questions', {
            order: 'desc',
            sort: 'activity',
            site: 'codegolf',
            filter: '!5RCKNP5Mc6Rvk2i(0CxGveeZ-' // This is from the SE api explorer
        });

        const entities = await import('entities');
        results.forEach(obj => {
            obj.title = entities.decodeHTML(obj.title);
            obj.body_markdown = entities.decodeHTML(obj.body_markdown);
        });

        return results;
    }
}