src/codeforces.js
function makeApiUrl(options,parameters) {

    var query = parameters;

    //
    // If any parameter given in array, make it string separated by semicolon(;)
    //
    for(let key in query){
        if( _.isArray(query[key]) ){
            query[key] = _.join(query[key],';');
        }
    }

    let curTime = Math.floor(Date.now() / 1000);
    let randomToken = randomstring.generate(6);

    query.time = curTime;
    query.apiKey  = options.API_KEY;

    //
    // Sort parameters according to codeforces API rules
    //
    query = _
        .chain(query)
        .map( (value, key) => {
            return { key, value };
        })
        .orderBy(['key', 'value'], ['desc', 'desc'])
        .reverse()
        .keyBy('key')
        .mapValues('value')
        .value();

    let qsFy = qs.stringify(query,{ encode: false });
    let apiSig = `${randomToken}/${options.method}?${qsFy}#${options.API_SECRET}`;

    apiSig = sha512(apiSig).toString();
    query.apiSig = randomToken + apiSig;
    qsFy = qs.stringify(query,{ encode: false });

    let url = `${options.API_URL}/${options.method}?${qsFy}`;

    return url;
}
function makeApiUrl(options,parameters) {

    var query = parameters;

    //
    // If any parameter given in array, make it string separated by semicolon(;)
    //
    for(let key in query){
        if( _.isArray(query[key]) ){
            query[key] = _.join(query[key],';');
        }
    }

    let curTime = Math.floor(Date.now() / 1000);
    let randomToken = randomstring.generate(6);

    query.time = curTime;
    query.apiKey  = options.API_KEY;

    //
    // Sort parameters according to codeforces API rules
    //
    query = _
        .chain(query)
        .map( (value, key) => {
            return { key, value };
        })
        .orderBy(['key', 'value'], ['desc', 'desc'])
        .reverse()
        .keyBy('key')
        .mapValues('value')
        .value();

    let qsFy = qs.stringify(query,{ encode: false });
    let apiSig = `${randomToken}/${options.method}?${qsFy}#${options.API_SECRET}`;

    apiSig = sha512(apiSig).toString();
    query.apiSig = randomToken + apiSig;
    qsFy = qs.stringify(query,{ encode: false });

    let url = `${options.API_URL}/${options.method}?${qsFy}`;

    return url;
}
function makeApiUrl ( options , parameters ) { var query = parameters ; // // If any parameter given in array, make it string separated by semicolon(;) // for ( let key in query ) { if ( _ . isArray ( query [ key ] ) ) { query [ key ] = _ . join ( query [ key ] , ';' ) ; } } let curTime = Math . floor ( Date . now ( ) / 1000 ) ; let randomToken = randomstring . generate ( 6 ) ; query . time = curTime ; query . apiKey = options . API_KEY ; // // Sort parameters according to codeforces API rules // query = _ . chain ( query ) . map ( ( value , key ) => { return { key , value } ; } ) . orderBy ( [ 'key' , 'value' ] , [ 'desc' , 'desc' ] ) . reverse ( ) . keyBy ( 'key' ) . mapValues ( 'value' ) . value ( ) ; let qsFy = qs . stringify ( query , { encode : false } ) ; let apiSig = ` ${ randomToken } ${ options . method } ${ qsFy } ${ options . API_SECRET } ` ; apiSig = sha512 ( apiSig ) . toString ( ) ; query . apiSig = randomToken + apiSig ; qsFy = qs . stringify ( query , { encode : false } ) ; let url = ` ${ options . API_URL } ${ options . method } ${ qsFy } ` ; return url ; }
Generate API url according to CF API rules

@param {array} options - main class options
@param {array} parameters - API url parameters [see doc]
@returns {string} - final url
Generate API url according to CF API rules