diff --git a/GESI.gs b/GESI.gs index 2ce1f48..ae464e3 100644 --- a/GESI.gs +++ b/GESI.gs @@ -1,1334 +1,1057 @@ - // Google ESI (GESI) - // Modified version of https://github.com/googlesamples/apps-script-oauth2 to work with EVE SSO/ESI endpoints - // - // /u/blacksmoke16 @ Reddit - // @Blacksmoke16#1684 @ Discord - app_version = '0.3.7.0'; - - // Setup variables used throughout script - CLIENT_ID = '7c382c66a6c8487d8b64e50daad86f9b'; - CLIENT_SECRET = 'CwcYrVs05AtIbqZkJH8OrBPYps6MAH72qQ1Gf68t'; - BASE_URL = 'https://esi.tech.ccp.is/v' - - // Setup endpoint and version list - endpoints = { - "skills": { - "version": 4, - "url": "/characters/{character_id}/skills/", - "name": "skills", - "description": "Default: LIST, LIST for list of skills, TOTAL for total skill points.", - "parameters": [ - { - "name": "option", - "description": "LIST for list of skills, TOTAL for total skill points." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "skillQueue": { - "version": 2, - "url": "/characters/{character_id}/skillqueue/", - "name": "skillQueue", - "description": "Returns the user\"s current skill queue.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "marketPrices": { - "version": 1, - "url": "/markets/prices/", - "name": "marketPrices", - "description": "Returns the avgerage and adjusted prices for various itemIDs.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "structureMarketOrders": { - "version": 1, - "url": "/markets/structures/{structure_id}/", - "name": "structureMarketOrders", - "description": "Returns all market orders in a given structure.", - "parameters": [ - { - "name": "structure_id", - "description": "StructureID of the structure to get market orders." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "itemTypes": { - "version": 3, - "url": "/universe/types/{type_id}/", - "name": "itemTypes", - "description": "Returns information about a type.", - "parameters": [ - { - "name": "ids", - "description": "Single typeID or list of typeIDs to lookup." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterAssets": { - "version": 1, - "url": "/characters/{character_id}/assets/", - "name": "characterAssets", - "description": "Returns a list of the character\"s assets", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterWallet": { - "version": 1, - "url": "/characters/{character_id}/wallet/", - "name": "characterWallet", - "description": "Returns the balance of your wallet.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterLoyalty": { - "version": 1, - "url": "/characters/{character_id}/loyalty/points/", - "name": "characterLoyalty", - "description": "Returns a list of loyalty points for all corporations the character has worked for.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "corporationLoyalty": { - "version": 1, - "url": "/loyalty/stores/{corporation_id}/offers/", - "name": "corporationLoyalty", - "description": "Returns a list of offers from a specific corporation\"s loyalty store.", - "parameters": [ - { - "name": "corporation_id", - "description": "Corporation ID to get the loyalty point store for." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterPlanets": { - "version": 1, - "url": "/characters/{character_id}/planets/", - "name": "characterPlanets", - "description": "Returns a list of all planetary colonies owned by a character.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterPlanetDetails": { - "version": 2, - "url": "/characters/{character_id}/planets/{planet_id}/", - "name": "characterPlanetDetails", - "description": "Returns full details on the layout of a single planetary colony, including links, pins and routes. ", - "parameters": [ - { - "name": "planet_id", - "description": "ID of the planet to get details on." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "planetSchematic": { - "version": 1, - "url": "/universe/schematics/{schematic_id}/", - "name": "planetSchematic", - "description": "Returns information on a planetary factory schematic.", - "parameters": [ - { - "name": "schematic_id", - "description": "ID of the schematic to get information on." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterBlueprints": { - "version": 1, - "url": "/characters/{character_id}/blueprints/", - "name": "characterBlueprints", - "description": "Returns a list of blueprints the character has.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterIndustryJobs": { - "version": 1, - "url": "/characters/{character_id}/industry/jobs/", - "name": "characterIndustryJobs", - "description": "Returns a list of industry jobs placed by a character.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterMarketOrders": { - "version": 1, - "url": "/characters/{character_id}/orders/", - "name": "characterMarketOrders", - "description": "Returns a list of market orders placed by a character.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterWalletJournal": { - "version": 1, - "url": "/characters/{character_id}/wallet/journal/", - "name": "characterWalletJournal", - "description": "Returns a character\"s wallet journal.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterContracts": { - "version": 1, - "url": "/characters/{character_id}/contracts/", - "name": "characterContracts", - "description": "Returns a list of a character\"s contracts.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterContractBids": { - "version": 1, - "url": "/characters/{character_id}/contracts/{contract_id}/bids/", - "name": "characterContractBids", - "description": "Returns bids on a particular auction contract.", - "parameters": [ - { - "name": "contract_id", - "description": "ID of the contract to get bids for." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterContractItems": { - "version": 1, - "url": "/characters/{character_id}/contracts/{contract_id}/items/", - "name": "characterContractItems", - "description": "Returns Items and details of a particular contract.", - "parameters": [ - { - "name": "contract_id", - "description": "ID of the contract to get information on." - }, - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "characterWalletTransactions": { - "version": 1, - "url": "/characters/{character_id}/wallet/transactions/", - "name": "characterWalletTransactions", - "description": "Returns a character\"s wallet transactions.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "industryFacilities": { - "version": 1, - "url": "/industry/facilities/", - "name": "industryFacilities", - "description": "Return a list of industry facilities.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - }, - "industrySystems": { - "version": 1, - "url": "/industry/systems/", - "name": "industrySystems", - "description": "Return cost indices for solar systems.", - "parameters": [ - { - "name": "opt_headers", - "description": "Default: True, Boolean if column headings should be listed or not." - } - ] - } - }; - - function onOpen() { - SpreadsheetApp.getUi().createMenu('GESI') - .addItem('Authorize Sheet', 'showSidebar') - .addSeparator() - .addItem('Reset Auth', 'clearService') - .addToUi(); - } - - - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Skills - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - - /** - * Returns a list of Skill names, current points in skill and current level or total skill points. - * @param {string} option Default: LIST, LIST for list of skills, TOTAL for total skill points. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of Skill names, current points in skill and current level or total skill points. - * @customfunction - */ - function skills(option, opt_headers) { - var skill_list = new Array(); - var ids = new Array(); - - var response = JSON.parse(getData_(arguments.callee.name)); - - if (option === undefined) { option = "LIST"; }; - option = option.toLowerCase(); - - if (option == 'list') { - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { skill_list.push(['Name', 'Active Level', 'Trained Level', 'SP In Skill']); }; - - for (var i = 0; i < response.skills.length; i++) { - ids.push(response.skills[i].skill_id); - skill_list.push([ - response.skills[i].skill_id, - response.skills[i].active_skill_level, - response.skills[i].trained_skill_level, - response.skills[i].skillpoints_in_skill - ]); - } - - var skill_names = id2name_(ids); - - for (var i = 0; i < skill_list.length; i++) { - for (var n = 0; n < skill_names.length; n++) { - if (skill_list[i][0] == skill_names[n].id) { - skill_list[i][0] = skill_names[n].name - } - } - } - } else if (option == 'total') { - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { skill_list.push('Total SP'); }; - skill_list.push(response.total_sp); - } - return skill_list; - } - - /** - * Returns the user's current skill queue. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns the users' current skill queue. - * @customfunction - */ - function skillQueue(opt_headers) { - var skills = new Array(); - var ids = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { skills.push(['Name', 'Finished Level', 'Start Date', 'Finish Date', 'Position']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - ids.push(response[i].skill_id); - skills.push([ - response[i].skill_id, - response[i].finished_level, - response[i].start_date, - response[i].finish_date, - response[i].queue_position - ]); - } - - var skill_names = id2name_(ids); - - for (var i = 0; i < skills.length; i++) { - for (var n = 0; n < skill_names.length; n++) { - if (skills[i][0] == skill_names[n].id) { - skills[i][0] = skill_names[n].name - } - } - } - - return skills; - } - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Market - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * Returns the avgerage and adjusted prices for various itemIDs. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns the avgerage and adjusted prices for various itemIDs. - * @customfunction - */ - function marketPrices(opt_headers) { - var items = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { items.push(['typeID', 'Adjusted Price', 'Average Price']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - items.push([ - response[i].type_id, - response[i].adjusted_price, - response[i].average_price - ]); - } - - return items; - } - - /** - * Returns all market orders in a given structure. - * @param {number} structure_id ID of the structure to get market orders for. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns all market orders in a given structure. - * @customfunction - */ - function structureMarketOrders(structure_id, opt_headers) { - var items = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { items.push(['Order ID', 'Buy Order?', 'Type ID', 'Location ID', 'Price', 'issued', 'Range', 'Duration', 'Min Volume', 'Remaining Volume', 'Total Volume']); }; - - var response = JSON.parse(getData_(arguments.callee.name,structure_id)); - - for (var i = 0; i < response.length; i++) { - items.push([ - response[i].order_id, - response[i].is_buy_order, - response[i].type_id, - response[i].location_id, - response[i].price, - response[i].issued, - response[i].range, - response[i].duration, - response[i].min_volume, - response[i].volume_remain, - response[i].volume_total - ]); - } - - return items; - } - - /** - * List of market orders placed by a character. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a ist of market orders placed by a character. - * @customfunction - */ - function characterMarketOrders(opt_headers) { - var orders_list = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { orders_list.push(['Order ID', 'Buy Order?', 'Type ID', 'State', 'Location ID', 'Station ID', 'Price', 'issued', 'Range', 'Escrow', 'Region ID', 'Duration', 'Is Corp?', 'Min Volume', 'Remaining Volume', 'Total Volume']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - orders_list.push([ - response[i].order_id, - response[i].is_buy_order, - response[i].type_id, - response[i].state, - response[i].location_id, - response[i].station_id, - response[i].price, - response[i].issued, - response[i].range, - response[i].escrow, - response[i].region_id, - response[i].duration, - response[i].is_corp, - response[i].min_volume, - response[i].volume_remain, - response[i].volume_total - ]); - } - return orders_list; - } - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Universe - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * Returns information about a type. - * @param {number/array} ids Single typeID or list of typeIDs to lookup. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns information about a type. - * @customfunction - */ - function itemTypes(ids, opt_headers) { - var items = new Array(); - var typeIDs = new Array(); - var array_length = ids.length; - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { items.push(['Type ID', 'Type Name', 'Volume', 'Group ID', 'Market Group ID', 'Published?']); }; - if (!Array.isArray(ids)) { typeIDs.push(ids); - array_length = 1; } else { typeIDs = ids; }; - - for (var i = 0; i < array_length; i++) { - var response = JSON.parse(getData_(arguments.callee.name, typeIDs[i])); - items.push([ - response.type_id, - response.name, - response.volume, - response.group_id, - response.market_group_id, - response.published - ]); - } - - return items;; - } - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Assets - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * Returns a list of the character's assets. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of the characters assets. - * @customfunction - */ - function characterAssets(opt_headers) { - var items = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { items.push(['ItemID', 'TypeID', 'Quantity', 'LocationID', 'Location Type', 'Location Flag']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - var quantity = 1; - if (!response[i].is_singleton) { quantity = response[i].quantity }; - items.push([ - response[i].item_id, - response[i].type_id, - quantity, - response[i].location_id, - response[i].location_type, - response[i].location_flag - ]); - } - return items; - } - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Loyalty - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * Returns Returns a list of loyalty points for all corporations the character has worked for. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of loyalty points for all corporations the character has worked for. - * @customfunction - */ - function characterLoyalty(opt_headers) { - var points = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { points.push(['Corporation ID', 'Loyalty Points']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - for (var i = 0; i < response.length; i++) { - points.push([ - response[i].corporation_id, - response[i].loyalty_points - ]); - } - return points; - } - - /** - * Returns a list of offers from a specific corporation's loyalty store. - * @param {number} corporation_id ID of the corporation to get the loyalty point store for. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of offers from a specific corporation's loyalty store. - * @customfunction - */ - function corporationLoyalty(corporation_id, opt_headers) { - var items = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { items.push(['Type ID', 'Quantity', 'ISK Cost', 'LP Cost', 'Offer ID', 'Required Item', 'Required Quantity']); }; - - var response = JSON.parse(getData_(arguments.callee.name, corporation_id)); - - for (var i = 0; i < response.length; i++) { - for (var r = 0; r < response[i].required_items.length; r++) { - - items.push([ - response[i].type_id, - response[i].quantity, - response[i].isk_cost, - response[i].lp_cost, - response[i].offer_id, - response[i].required_items[r].type_id, - response[i].required_items[r].quantity - ]); - }; - }; - return items; - } - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Wallet - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * Returns the balance of your wallet. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns the balance of your wallet. - * @customfunction - */ - function characterWallet(opt_headers) { - var wallet_data = new Array(); - - if (opt_headers === undefined) opt_headers = true; - if (opt_headers) { wallet_data.push(['Balance']); }; - - var response = getData_(arguments.callee.name); - - wallet_data.push([parseFloat(response)]); - - return wallet_data; - } - - /** - * Retrieve character wallet journal. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Retrieve character wallet journal. - * @customfunction - */ - function characterWalletJournal(opt_headers) { - var entries = new Array(); - - if (opt_headers === undefined) opt_headers = true; - if (opt_headers) entries.push(['Ref ID', 'Date', 'Ref Type', 'Amount', 'Balance', 'Description', 'Tax Reciver ID', 'First Party Type', 'First Party ID', 'Second Party Type', 'Second Party ID', 'Extra Info:']); - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - entries.push([ - response[i].ref_id, - response[i].date, - response[i].ref_type, - response[i].amount, - response[i].balance, - response[i].reason, - response[i].tax_reciever_id, - response[i].first_party_type, - response[i].first_party_id, - response[i].second_party_type, - response[i].second_party_id - ]); - if (!(response[i].hasOwnProperty('extra_info'))) continue; - if (i === 0) entries[i].push('Alliance ID', 'Character ID', 'Corporation ID', 'Contract ID', 'Destroyed Ship Type ID', 'Job ID', 'Location ID', 'NPC ID', 'NPC Name', 'Planet ID', 'System ID', 'Transaction ID'); - entries[i].push( - '', - response[i].extra_info.alliance_id, - response[i].extra_info.character_id, - response[i].extra_info.corporation_id, - response[i].extra_info.contract_id, - response[i].extra_info.destroyed_ship_type_id, - response[i].extra_info.job_id, - response[i].extra_info.location_id, - response[i].extra_info.npc_id, - response[i].extra_info.npc_name, - response[i].extra_info.planet_id, - response[i].extra_info.system_id, - response[i].extra_info.transaction_id - ); - } - return entries; - } - - /** - * Retrieve character wallet transactions. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Retrieve character wallet transactions. - * @customfunction - */ - function characterWalletTransactions(opt_headers) { - var transactions = new Array(); - - if (opt_headers === undefined) opt_headers = true; - if (opt_headers) transactions.push(['Transaction ID', 'Client ID', 'Date', 'Type ID', 'Quantity', 'Unit Price', 'Location ID', 'Is Buy?', 'Is Personal?', 'Journal Ref ID']); - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - transactions.push([ - response[i].transaction_id, - response[i].client_id, - response[i].date, - response[i].type_id, - response[i].quantity, - response[i].unit_price, - response[i].location_id, - response[i].is_buy, - response[i].is_personal, - response[i].journal_ref_id - ]); - } - return transactions; - } - - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Planets - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * Returns a list of all planetary colonies owned by a character. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of all planetary colonies owned by a character. - * @customfunction - */ - function characterPlanets(opt_headers) { - var planets = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { planets.push(['Planet ID', 'Type', 'System ID', 'Owner ID', 'Upgrade Level', 'Last Updated', '# Pins']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - planets.push([ - response[i].planet_id, - capitalize_(response[i].planet_type), - response[i].solar_system_id, - response[i].owner_id, - response[i].upgrade_level, - response[i].last_update, - response[i].num_pins - ]); - } - return planets; - } - - - /** - * Returns full details on the layout of a single planetary colony, including links, pins and routes. - * @param {number} planet_id ID of the planet to get details on. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns full details on the layout of a single planetary colony, including links, pins and routes. - * @customfunction - */ - function characterPlanetDetails(planet_id, opt_headers) { - var planets = new Array(); - - if (planet_id === undefined) {throw new Error("No planet ID specified." )}; - - var response = JSON.parse(getData_(arguments.callee.name, planet_id)); - - // Inserting header for Links - planets.push(['Links']); - - // Insert data values for links - planets.push(['', 'Source Pin ID', 'Dest Pin ID', 'Link Level']); - - for(var i = 0; i < response.links.length;i++){ - planets.push([ - '', - response.links[i].source_pin_id, - response.links[i].destination_pin_id, - response.links[i].link_level - ]); - } - - // Inserting header for Pins - planets.push(['Pins']); - - // Insert data values for Pins - planets.push(['', 'Pin ID', 'Type ID', 'Latitude', 'Longitude', 'Schematic ID', 'Last Cycle Start']); - - var schematic = null; - var last_start_time = null; - - for(var i = 0; i < response.pins.length;i++){ - if(!(response.pins[i].hasOwnProperty("schematic_id"))){schematic = "N/A"} else {schematic = response.pins[i].schematic_id} - if(!(response.pins[i].hasOwnProperty("last_cycle_start"))){last_start_time = "N/A"} else {last_start_time = response.pins[i].last_cycle_start} - - planets.push([ - '', - response.pins[i].pin_id, - response.pins[i].type_id, - response.pins[i].latitude, - response.pins[i].longitude, - schematic, - last_start_time - ]); - } - - // Inserting header for Pins - planets.push(['Extractors']); - - // Insert data values for Pins - planets.push(['', 'Pin ID','Product Type ID', 'Cycle Time', 'Head Radius', 'Quantity Per Cycle']); - - for(var i = 0; i < response.pins.length;i++){ - if( !("extractor_details" in response.pins[i])){ continue;} - planets.push(['', - response.pins[i].pin_id, - response.pins[i].extractor_details.product_type_id, - response.pins[i].extractor_details.cycle_time, - response.pins[i].extractor_details.head_radius, - response.pins[i].extractor_details.qty_per_cycle - ]); - } - - // Inserting header for Routes - planets.push(['Routes']); - - // Insert data values for Routes - planets.push(['', 'Route ID', 'Source Pin ID', 'Dest Pin ID', 'Content Type ID', 'Quantity']); - - for(var i = 0; i < response.routes.length;i++){ - planets.push(['', - response.routes[i].route_id, - response.routes[i].source_pin_id, - response.routes[i].destination_pin_id, - response.routes[i].content_type_id, - response.routes[i].quantity - ]); - } - - - return planets; - } - - /** - * Returns information on a planetary factory schematic. - * @param {number} schematic_id ID of the schematic to get information on. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns information on a planetary factory schematic. - * @customfunction - */ - function planetSchematic(schematic_id, opt_headers) { - var schematic_data = new Array(); - - if (schematic_id === undefined) {throw new Error("No schematic ID specified." )}; - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { schematic_data.push(['Name', 'Cycle Time']); }; - - var response = JSON.parse(getData_(arguments.callee.name, schematic_id)); - - schematic_data.push([response.schematic_name, response.cycle_time]); - - return schematic_data; - } - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Character - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * List of blueprints the character has. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of blueprints the character has. - * @customfunction - */ - function characterBlueprints(opt_headers) { - var blueprint_list = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { blueprint_list.push(['Item ID', 'Type ID', 'Runs', 'ME', 'TE', 'Quantity', 'Location ID', 'Location Flag']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - blueprint_list.push([ - response[i].item_id, - response[i].type_id, - response[i].runs, - response[i].material_efficiency, - response[i].time_efficiency, - response[i].quantity, - response[i].location_id, - response[i].location_flag - ]); - } - return blueprint_list; - } - - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Industry - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * List of industry jobs placed by a character. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of industry jobs placed by a character. - * @customfunction - */ - function characterIndustryJobs(opt_headers) { - var job_list = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { job_list.push(['Job ID','Type ID', 'Activity ID', 'Runs', 'Cost', 'Status', 'Duration', 'Licensed Runs', 'Installer ID', 'Facility ID', 'Start Date', 'End Date', 'Blueprint ID', 'Blueprint Location ID', 'Output Location ID', 'Station ID']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - job_list.push([ - response[i].job_id, - response[i].blueprint_type_id, - response[i].activity_id, - response[i].runs, - response[i].cost, - response[i].status, - response[i].duration, - response[i].licensed_runs, - response[i].installer_id, - response[i].facility_id, - response[i].start_date, - response[i].end_date, - response[i].blueprint_id, - response[i].blueprint_location_id, - response[i].output_location_id, - response[i].station_id - ]); - } - return job_list; - } - - /** - * Return a list of industry facilities. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns a list of industry facilities. - * @customfunction - */ - function industryFacilities(opt_headers) { - var facilities = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { facilities.push(['Facility ID', 'Owner ID', 'Region ID', 'Solar System ID', 'Tax', 'Type ID']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - facilities.push([ - response[i].facility_id , - response[i].owner_id , - response[i].region_id, - response[i].solar_system_id, - response[i].tax, - response[i].type_id - ]); - } - return facilities; - } - - /** - * Return cost indices for solar systems. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Return cost indices for solar systems. - * @customfunction - */ - function industrySystems(opt_headers) { - var cost_indices = new Array(); - - if (opt_headers === undefined) { opt_headers = true; }; - if (opt_headers) { cost_indices.push(['Solar System ID']); }; - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - cost_indices.push([ response[i].solar_system_id ]); - - cost_indices.push([ - '', - response[i].cost_indices[0].activity, - response[i].cost_indices[1].activity, - response[i].cost_indices[2].activity, - response[i].cost_indices[3].activity, - response[i].cost_indices[4].activity - ]); - - cost_indices.push([ - '', - response[i].cost_indices[0].cost_index, - response[i].cost_indices[1].cost_index, - response[i].cost_indices[2].cost_index, - response[i].cost_indices[3].cost_index, - response[i].cost_indices[4].cost_index - ]); - - } - return cost_indices; - } - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Contracts - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /** - * Returns contracts available to a character. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns contracts available to a character, only if the character is issuer, acceptor or assignee. Only returns contracts no older than 30 days, or if the status is "in_progress." - * @customfunction - */ - function characterContracts(opt_headers) { - var contracts = new Array(); - - if (opt_headers === undefined) opt_headers = true; - if (opt_headers) contracts.push(['Contract ID','Availability','Issuer ID','Status','Title','Type','Volume','Price','Buyout','Reward','Collateral','Start Location ID','End Location ID','Acceptor ID','Assignee ID','Date Issued','Date Accepted','Date Completed','Date Expired','Days To Complete','For Corporation','Issuer Corporation ID']); - - var response = JSON.parse(getData_(arguments.callee.name)); - - for (var i = 0; i < response.length; i++) { - contracts.push([ - response[i].contract_id, - response[i].availability, - response[i].issuer_id, - response[i].status, - response[i].title, - response[i].type, - response[i].volume, - response[i].price, - response[i].buyout, - response[i].reward, - response[i].collateral, - response[i].start_location_id, - response[i].end_location_id, - response[i].acceptor_id, - response[i].assignee_id, - response[i].date_issued, - response[i].date_accepted, - response[i].date_completed, - response[i].date_expired, - response[i].days_to_complete, - response[i].for_corporation, - response[i].issuer_corporation_id - ]); - } - return contracts; - - } - - /** - * Returns bids on a particular auction contract. - * @param {integer} contract_id Contract ID to get bids for. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns bids on a particular auction contract. - * @customfunction - */ - function characterContractBids(contract_id, opt_headers) { - var bids = new Array(); - - if (opt_headers === undefined) opt_headers = true; - if (opt_headers) bids.push(['Bid ID', 'Date Bid', 'Bidder ID', 'Amount']); - - var response = JSON.parse(getData_(arguments.callee.name,contract_id)); - - for (var i = 0; i < response.length; i++) { - bids.push([ - response[i].bid_id, - response[i].date_bid, - response[i].bidder_id, - response[i].amount - ]); - } - return bids; - - } - - - /** - * Returns items and details of a particular contract. - * @param {integer} contract_id Contract ID to get items for. - * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. - * @return Returns items and details of a particular contract. - * @customfunction - */ - function characterContractItems(contract_id, opt_headers) { - var items = new Array(); - - if (opt_headers === undefined) opt_headers = true; - if (opt_headers) items.push(['Record ID', 'Type ID', 'Quantity', 'Is Included?', 'Is Singleton?', 'Raw Quantity']); - - var response = JSON.parse(getData_(arguments.callee.name,contract_id)); - - for (var i = 0; i < response.length; i++) { - items.push([ - response[i].record_id, - response[i].type_id, - response[i].quantity, - response[i].is_included, - response[i].is_singleton, - response[i].raw_quantity - ]); - } - return items; - - } - - - - - - - - - - - - - - - - - - - +// Google ESI (GESI) +// Modified version of https://github.com/googlesamples/apps-script-oauth2 to work with EVE SSO/ESI endpoints +// +// /u/blacksmoke16 @ Reddit +// @Blacksmoke16#1684 @ Discord +app_version = '2.0.0'; + +// Setup variables used throughout script +CLIENT_ID = '7c382c66a6c8487d8b64e50daad86f9b'; +CLIENT_SECRET = 'CwcYrVs05AtIbqZkJH8OrBPYps6MAH72qQ1Gf68t'; +BASE_URL = 'https://esi.tech.ccp.is/v' + +CHARACTERS = ['Blacksmoke16']; + +AUTHING_CHARACTER = CHARACTERS[0]; + +URL_PARAMS = ['{event_id}', '{alliance_id}', '{schematic_id}', '{corporation_id}', '{division}', '{war_id}', '{planet_id}', '{type_id}', '{contract_id}', '{structure_id}']; + +ENDPOINTS = { + // Alliances + + "allianceIds": { + "version": 1, + "url": "/alliances/", + "headers": ['alliance_ids'] + }, + "allianceNames": { + "version": 1, + "url": "/alliances/names/", + "headers": ['alliance_id', 'alliance_name'] + }, + "allianceId": { + "version": 2, + "url": "/alliances/{alliance_id}/", + "headers": ['alliance_name', 'ticker', 'executor_corp', 'date_founded'] + }, + "allianceCorporations": { + "version": 1, + "url": "/alliances/{alliance_id}/corporations/", + "headers": ['corporation_ids'] + }, + "allianceIcons": { + "version": 1, + "url": "/alliances/{alliance_id}/icons/", + "headers": ['px128x128', 'px64x64'] + }, + + // Assets + + "characterAssets": { + "version": 1, + "url": "/characters/{character_id}/assets/", + "headers": ['item_id', 'type_id', 'quantity', 'location_id', 'location_type', 'location_flag'] + }, + + // Bookmarks + + "characterBookmarks": { + "version": 1, + "url": "/characters/{character_id}/bookmarks/", + "headers": ['bookmark_id', 'target-location_id', 'memo', 'create_date', 'creator_id', 'note', 'owner_id', 'folder_id', 'target-item-item_id', 'target-item-type_id'] + }, + "characterBookmarkFolders": { + "version": 1, + "url": "/characters/{character_id}/bookmarks/folders", + "headers": ['folder_id', 'name', 'owner_id'] + }, + + // Calendar + + "calenderEvents": { + "version": 1, + "url": "/characters/{character_id}/calendar/", + "headers": ['event_id', 'title', 'event_date', 'event_response', 'importance'] + }, + "calenderEvent": { + "version": 3, + "url": "/characters/{character_id}/calendar/{event_id}/", + "headers": ['event_id', 'date', 'title', 'text', 'duration', 'owner_id', 'owner_name', 'owner_type', 'response', 'importance'] + }, + + // Characters + + "characterBlueprints": { + "version": 1, + "url": "/characters/{character_id}/blueprints/", + "headers": ['item_id', 'type_id', 'location_id', 'location_flag', 'material_efficiency', 'time_efficiency', 'runs', 'quantity'] + }, + + // Contracts + + "characterContracts": { + "version": 1, + "url": "/characters/{character_id}/contracts/", + "headers": ['contract_id', 'issuer_id', 'assignee_id', 'acceptor_id', 'availability', 'type', 'title', 'status', 'issuer_corporation_id', 'for_corporation', 'date_issued', 'date_accepted', 'date_completed', 'date_expired', 'price', 'buyout', 'reward', 'collateral', 'volume', 'days_to_complete', 'start_location_id', 'end_location_id'] + }, + "characterContractsBids": { + "version": 1, + "url": "/characters/{character_id}/contracts/{contract_id}/bids/", + "headers": ['bid_id', 'date_bid', 'bidder_id', 'amount'] + }, + "characterContractItems": { + "version": 1, + "url": "/characters/{character_id}/contracts/{contract_id}/items/", + "headers": ['record_id', 'type_id', 'quantity', 'raw_quantity', 'is_included', 'is_singleton'] + }, + + // Industry + + "characterIndustryJobs": { + "version": 1, + "url": "/characters/{character_id}/industry/jobs/", + "headers": ['job_id', 'activity_id', 'blueprint_id', 'blueprint_location_id', 'blueprint_type_id', 'completed_character_id', 'completed_date', 'cost', 'duration', 'end_date', 'facility_id', 'installer_id', 'licensed_runs', 'output_location_id', 'pause_date', 'probability', 'product_type_id', 'runs', 'start_date', 'station_id', 'status', 'successful_runs'] + }, + "industryFacilities": { + "version": 1, + "url": "/industry/facilities/", + "headers": ['facility_id', 'type_id', 'solar_system_id', 'region_id', 'tax', 'owner_id'] + }, + "industrySystems": { + "version": 1, + "url": "/industry/systems/", + "headers": ['solar_system_id', 'manufacturing', 'researching_material_efficiency', 'researching_time_efficiency', 'copying', 'invention'] + }, + + // Loyalty + + "characterLoyalty": { + "version": 1, + "url": "/characters/{character_id}/loyalty/points/", + "headers": ['corporation_id', 'loyalty_points'] + }, + "corporationLoyalty": { + "version": 1, + "url": "/loyalty/stores/{corporation_id}/offers/", + "headers": ['offer_id', 'type_id', 'lp_cost', 'isk_cost', 'quantity'] + }, + + // Market + + "characterOrders": { + "version": 1, + "url": "/characters/{character_id}/orders/", + "headers": ['order_id', 'type_id', 'state', 'location_id', 'issued', 'is_buy_order', 'is_corp', 'account_id', 'price', 'escrow', 'range', 'volume_remain', 'volume_total', 'min_volume', 'duration'] + }, + "marketPrices": { + "version": 1, + "url": "/markets/prices/", + "headers": ['type_id', 'average_price', 'adjusted_price'] + }, + "structureOrders": { + "version": 1, + "url": "/markets/structures/{structure_id}/", + "headers": ['order_id', 'type_id', 'location_id', 'issued', 'is_buy_order', 'price', 'range', 'volume_remain', 'volume_total', 'min_volume', 'duration'] + }, + + // Planets + + "characterPlanets": { + "version": 1, + "url": "/characters/{character_id}/planets/", + "headers": ['planet_id', 'planet_type', 'solar_system_id', 'owner_id', 'upgrade_level', 'last_update', 'num_pins'] + }, + "characterPlanetDetails": { + "version": 3, + "url": "/characters/{character_id}/planets/{planet_id}/" + }, + "planetSchematic": { + "version": 1, + "url": "/universe/schematics/{schematic_id}/", + "headers": ['schematic_name', 'cycle_time'] + }, + + // Skills + + "characterAttributes": { + "version": 1, + "url": "/characters/{character_id}/attributes/", + "headers": ['charisma', 'intelligence', 'perception', 'memory', 'willpower'] + }, + "skillQueue": { + "version": 2, + "url": "/characters/{character_id}/skillqueue/", + "headers": ['skill_id', 'queue_position', 'finished_level', 'start_date', 'finish_date'] + }, + "characterSkills": { + "version": 4, + "url": "/characters/{character_id}/skills/", + "headers": ['skill_id', 'active_skill_level', 'trained_skill_level', 'skillpoints_in_skill'] + }, + + // Universe + "typeId": { + "version": 3, + "url": "/universe/types/{type_id}/", + "headers": ['type_id', 'name', 'group_id', 'description', 'capacity', 'volume', 'packaged_volume', 'portion_size', 'radius', 'mass', 'market_group_id', 'icon_id', 'graphic_id', 'published'] + }, + + // Wallet + + "characterWallet": { + "version": 1, + "url": "/characters/{character_id}/wallet/", + "headers": ['balance'] + }, + "characterWalletJournal": { + "version": 1, + "url": "/characters/{character_id}/wallet/journal", + "headers": ['ref_id', 'date', 'amount', 'balance', 'first_party_id', 'first_party_type', 'reason', 'ref_type', 'second_party_id ', 'second_party_type', 'tax', 'tax_reciever_id', 'extra_info-alliance_id', 'extra_info-character_id', 'extra_info-contract_id', 'extra_info-destroyed_ship_type_id', 'extra_info-job_id', 'extra_info-location_id', 'extra_info-npc_id', 'extra_info-npc_name', 'extra_info-planet_id', 'extra_info-system_id', 'extra_info-transaction_id'] + }, + "characterWalletTransactions": { + "version": 1, + "url": "/characters/{character_id}/wallet/transactions/", + "headers": ['transaction_id', 'date', 'quantity', 'type_id', 'unit_price', 'location_id', 'journal_ref_id', 'client_id', 'is_buy', 'is_personal'] + }, + "corporationWallets": { + "version": 1, + "url": "/corporations/{corporation_id}/wallets/", + "headers": ['division', 'balance'] + }, + "corporationWalletJournal": { + "version": 1, + "url": "/corporations/{corporation_id}/wallets/{division}/journal/", + "headers": ['ref_id', 'date', 'amount', 'balance', 'first_party_id', 'first_party_type', 'reason', 'ref_type', 'second_party_id ', 'second_party_type', 'tax', 'tax_reciever_id', 'extra_info-alliance_id', 'extra_info-character_id', 'extra_info-contract_id', 'extra_info-destroyed_ship_type_id', 'extra_info-job_id', 'extra_info-location_id', 'extra_info-npc_id', 'extra_info-npc_name', 'extra_info-planet_id', 'extra_info-system_id', 'extra_info-transaction_id'] + }, + + // Wars + + "wars": { + "version": 1, + "url": "/wars", + "headers": ['war_ids'] + }, + "war": { + "version": 1, + "url": "/wars/{war_id}/", + "headers": ['id', 'mutual', 'open_for_allies', 'declared', 'started', 'finished', 'aggressor-corporation_id', 'aggressor-alliance_id', 'aggressor-isk_destroyed', 'aggressor-ships_killed', 'defender-corporation_id', 'defender-alliance_id', 'defender-isk_destroyed', 'defender-ships_killed', 'ally-alliance_id', 'ally-corporation_id'] + }, + "warKillmails": { + "version": 1, + "url": "/wars/{war_id}/killmails", + "headers": ['killmail_id', 'killmail_hash'] + } +}; + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Alliances +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Returns a list of Alliance IDs + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Returns a list of Alliance IDs. + * @customfunction + */ +function allianceIds(opt_headers) { + return getArrayResponse_(arguments.callee.name, '', opt_headers); +} + +/** + * Resolve a set of alliance IDs to alliance names + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Returns a list of id/name associations. + * @customfunction + */ +function allianceNames(alliance_ids, opt_headers) { + if (!alliance_ids) throw 'A range of alliance ids is required'; + return getArrayObjectResponse_(arguments.callee.name, '', opt_headers, {alliance_ids: alliance_ids}); +} + +/** + * Public information about an alliance + * @param {number} alliance_id ID of the alliance to get information on + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Public data about an alliance + * @customfunction + */ +function allianceId(alliance_id, opt_headers) { + if (!alliance_id) throw 'alliance_id is required'; + return getObjectResponse_(arguments.callee.name, '', opt_headers, {alliance_id: alliance_id}); +} + +/** + * List all current member corporations of an alliance + * @param {number} alliance_id ID of the alliance to get corporations for + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return List of corporation IDs + * @customfunction + */ +function allianceCorporations(alliance_id, opt_headers) { + if (!alliance_id) throw 'alliance_id is required'; + return getArrayResponse_(arguments.callee.name, '', opt_headers, {alliance_id: alliance_id}); +} + +/** + * Get the icon urls for a alliance + * @param {number} alliance_id ID of the alliance to get icons for + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Urls for icons for the given alliance id and server + * @customfunction + */ +function allianceIcons(alliance_id, opt_headers) { + if (!alliance_id) throw 'alliance_id is required'; + return getObjectResponse_(arguments.callee.name, '', opt_headers, {alliance_id: alliance_id}); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Assets +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Returns a list of the character's assets. + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Returns a list of the characters assets. + * @customfunction + */ +function characterAssets(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Bookmarks +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * List your character's personal bookmarks + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of bookmarks + * @customfunction + */ +function characterBookmarks(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true, true); +} + +/** + * List your character's personal bookmark folders + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return List of bookmark folders + * @customfunction + */ +function characterBookmarkFolders(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Calendar +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Get 50 event summaries from the calendar. + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A collection of event summaries + * @customfunction + */ +function calenderEvents(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Get all the information for a specific event + * @param {number} event_id ID of the event to get information for + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Full details of a specific event + * @customfunction + */ +function calenderEvent(event_id, name, opt_headers) { + if (!event_id) throw 'An event id is required'; + return getObjectResponse_(arguments.callee.name, name, opt_headers, {event_id: event_id}, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Character +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Return a list of blueprints the character has + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of blueprints + * @customfunction + */ +function characterBlueprints(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Contracts +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Returns contracts available to a character, only if the character is issuer, acceptor or assignee. + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of contracts + * @customfunction + */ +function characterContracts(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Return cost indices for solar systems + * @param {number} contract_id of the contract to get bids for + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of bids + * @customfunction + */ +function characterContractBids(contract_id, name, opt_headers) { + if (!contract_id) throw 'contract_id is required'; + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {contract_id: contract_id}, true); +} + +/** + * Lists Items and details of a particular contract + * @param {number} contract_id of the contract to get items for + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of items + * @customfunction + */ +function characterContractItems(contract_id, name, opt_headers) { + if (!contract_id) throw 'contract_id is required'; + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {contract_id: contract_id}, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Industry +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * List industry jobs placed by a character + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Industry jobs placed by a character + * @customfunction + */ +function characterIndustryJobs(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Return a list of industry facilities + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of facilities + * @customfunction + */ +function industryFacilities(opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, '', opt_headers, {}); +} + +/** + * Return cost indices for solar systems + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of cost indicies + * @customfunction + */ +function industrySystems(opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, '', opt_headers, {}, false, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Loyalty +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Return a list of loyalty points for all corporations the character has worked for + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of loyalty points + * @customfunction + */ +function characterLoyalty(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Return a list of offers from a specific corporation's loyalty store + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of offers + * @customfunction + */ +function corporationLoyalty(corporation_id, opt_headers) { + if (!corporation_id) throw 'corporation_id is required'; + return getArrayObjectResponse_(arguments.callee.name, '', opt_headers, {corporation_id: corporation_id}, false); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Market +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * List market orders placed by a character + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Market orders placed by a character + * @customfunction + */ +function characterOrders(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Return a list of prices + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of prices + * @customfunction + */ +function marketPrices(opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, '', opt_headers, {}); +} + +/** + * Return a list of prices + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of prices + * @customfunction + */ +function structureOrders(structure_id, name, opt_headers) { + if (!structure_id) throw 'structure_id is required'; + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {structure_id: structure_id}, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Planets +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Returns a list of all planetary colonies owned by a character. + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Returns a list of all planetary colonies owned by a character. + * @customfunction + */ +function characterPlanets(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Returns full details on the layout of a single planetary colony, including links, pins and routes. + * @param {number} planet_id of the planet to get details on + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Colony layout + * @customfunction + */ +function characterPlanetDetails(planet_id, name, opt_headers) { + if (!planet_id) throw 'planet_id is required'; + return characterPlanetDetails_({planet_id: planet_id}, name, opt_headers, true); +} + +/** + * Returns information on a planetary factory schematic. + * @param {number} schematic_id ID of the schematic to get information on. + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Returns information on a planetary factory schematic. + * @customfunction + */ +function planetSchematic(schematic_id, name, opt_headers) { + if (!schematic_id) throw 'schematic_id is required'; + return getObjectResponse_(arguments.callee.name, name, opt_headers, {schematic_id: schematic_id}) +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Skills +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Return attributes of a character + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Attributes of a character + * @customfunction + */ +function characterAttributes(name, opt_headers) { + return getObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * List the configured skill queue for the given character + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return The current skill queue, sorted ascending by finishing time + * @customfunction + */ +function skillQueue(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * List all trained skills for the given character + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Known skills for the character + * @customfunction + */ +function characterSkills(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Universe +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Get information on a type + * @param {string} type_id type_id of item to get information on + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Information about a type + * @customfunction + */ +function typeId(type_id, opt_headers) { + if (!type_id) throw 'type_id is required'; + return getObjectResponse_(arguments.callee.name, '', opt_headers, {type_id: type_id}); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Wallet +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Returns a character's wallet balance + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return balance + * @customfunction + */ +function characterWallet(name, opt_headers) { + return getSingleResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Retrieve character wallet journal + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Journal entries + * @customfunction + */ +function characterWalletJournal(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Get wallet transactions of a character + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Wallet transactions + * @customfunction + */ +function characterWalletTransactions(name, opt_headers) { + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {}, true); +} + +/** + * Get a corporation's wallets + * @param {number} corporation_id ID of the corporation to get wallets for + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return List of corporation wallets + * @customfunction + */ +function corporationWallets(corporation_id, name, opt_headers) { + if (!corporation_id) throw 'corporation_id is required'; + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, {corporation_id: corporation_id}, true); +} + +/** + * Retrieve corporation wallet journal + * @param {number} corporation_id ID of the corporation to get wallet journal for + * @param {number} division ID of the division to get wallet journal from + * @param {string} name Name of the character used for auth. If none is given, defaults to AUTHING_CHARACTER. + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Journal entries + * @customfunction + */ +function corporationWalletJournal(corporation_id, division, name, opt_headers) { + if (!corporation_id) throw 'corporation_id is required'; + if (!division) throw 'division is required'; + corporation_id = 98019139; + division = 1; + return getArrayObjectResponse_(arguments.callee.name, name, opt_headers, { + corporation_id: corporation_id, + division: division + }, true, true); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Wars +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Return a list of wars + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of war IDs, in decending order by war_id. + * @customfunction + */ +function wars(opt_headers) { + return getArrayResponse_(arguments.callee.name, '', opt_headers); +} + +/** + * Return details about a war + * @param {number} war_id ID of the war to get information on + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return Details about a war + * @customfunction + */ +function war(war_id, opt_headers) { // 291410 RVB War ID + if (!war_id) throw 'war_id is required'; + return getObjectResponse_(arguments.callee.name, '', opt_headers, {war_id: war_id}, false, true); +} + +/** + * Return a list of kills related to a war + * @param {number} war_id ID of the war to get killmails for + * @param {boolean} opt_headers Default: True, Boolean if column headings should be listed or not. + * @return A list of killmail IDs and hashes + * @customfunction + */ +function warKillmails(war_id, opt_headers) { + if (!war_id) throw 'war_id is required'; + return getArrayObjectResponse_(arguments.callee.name, '', opt_headers, {war_id: war_id}); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Private Functions +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +function getData_(endpoint_name, name, params) { + var userProperties = PropertiesService.getUserProperties(); + var eveService = createOAuthForUser(name); + var url = ENDPOINTS[endpoint_name].url + + if (url.indexOf('{character_id}') !== -1) { + url = url.replace('{character_id}', parseInt(userProperties.getProperty(name))); + } + for (var p = 0; p < URL_PARAMS.length; p++) { + if (url.indexOf(URL_PARAMS[p]) !== -1) { + url = url.replace(URL_PARAMS[p], params[URL_PARAMS[p].replace('{', '').replace('}', '')]); + } + } + var response = UrlFetchApp.fetch(BASE_URL + ENDPOINTS[endpoint_name].version + url, { + headers: { + Authorization: 'Bearer ' + eveService.getAccessToken() + } + }); + if (!response) throw 'Error getting ESI data'; + return JSON.parse(response); +} +function getUnauthedData_(endpoint_name, name, params) { + var url = BASE_URL + ENDPOINTS[endpoint_name].version + ENDPOINTS[endpoint_name].url; + if (endpoint_name === 'allianceNames') url = url + '?alliance_ids=' + params.join(); + for (var p = 0; p < URL_PARAMS.length; p++) { + if (url.indexOf(URL_PARAMS[p]) !== -1) { + url = url.replace(URL_PARAMS[p], params[URL_PARAMS[p].replace('{', '').replace('}', '')]); + } + } + var response = UrlFetchApp.fetch(url); + if (!response) throw 'Error getting public ESI data'; + return JSON.parse(response); +} +function getArrayObjectResponse_(endpoint_name, name, opt_headers, params, authed, isNested) { + if (!name) name = AUTHING_CHARACTER; + if (authed) { + var data = getData_(endpoint_name, name, params); + } else { + var data = getUnauthedData_(endpoint_name, name, params); + } + if (endpoint_name === 'industrySystems') data = deArrayIndex_(data); + var result = []; + if (opt_headers === undefined) opt_headers = true; + if (opt_headers) result.push(convertSnakeCase_(ENDPOINTS[endpoint_name].headers)); + + for (var i = 0; i < data.length; i++) { + var temp = []; + if (isNested) data[i] = flatten_(data[i]); + for (var k = 0; k < ENDPOINTS[endpoint_name].headers.length; k++) { + data_value = data[i][ENDPOINTS[endpoint_name].headers[k]]; + temp.push(data_value); + } + result.push(temp); + } + Logger.log(result); + return result; +}; +function getObjectResponse_(endpoint_name, name, opt_headers, params, authed, isNested) { + if (!name) name = AUTHING_CHARACTER; + if (authed) { + var data = getData_(endpoint_name, name, params); + } else { + var data = getUnauthedData_(endpoint_name, name, params); + } + var result = []; + if (opt_headers === undefined) opt_headers = true; + if (opt_headers) result.push(convertSnakeCase_(ENDPOINTS[endpoint_name].headers)); + if (isNested) data = flatten_(data); + + var temp = []; + for (var k = 0; k < ENDPOINTS[endpoint_name].headers.length; k++) { + temp.push(data[ENDPOINTS[endpoint_name].headers[k]]); + } + result.push(temp); + return result; +}; +// Private function for basic array of value responses +function getArrayResponse_(endpoint_name, name, opt_headers, params, authed) { + if (!name) name = AUTHING_CHARACTER; + if (authed) { + var data = getData_(endpoint_name, name, params); + } else { + var data = getUnauthedData_(endpoint_name, name, params); + } + var result = []; + if (opt_headers === undefined) opt_headers = true; + if (opt_headers) result.push(convertSnakeCase_(ENDPOINTS[endpoint_name].headers)); + for (var i = 0; i < data.length; i++) { + result.push(data[i]); + } + ; + + return result; +}; + +// Private function for basic array of value responses +function getSingleResponse_(endpoint_name, name, opt_headers, params, authed) { + if (!name) name = AUTHING_CHARACTER; + if (authed) { + var data = getData_(endpoint_name, name, params); + } else { + var data = getUnauthedData_(endpoint_name, name, params); + } + var result = []; + if (opt_headers === undefined) opt_headers = true; + if (opt_headers) result.push(convertSnakeCase_(ENDPOINTS[endpoint_name].headers)); + result.push(data); + return result; +}; - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // OAth2 Functions - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +function flatten_(ob) { + var toReturn = {}; + for (var i in ob) { + if (!ob.hasOwnProperty(i)) continue; - function getEVEService() { - // Create a new service with the given name. The name will be used when - // persisting the authorized token, so ensure it is unique within the - // scope of the property store. - return OAuth2.createService('EVE') + if ((typeof ob[i]) == 'object') { + var flatObject = flatten_(ob[i]); + for (var x in flatObject) { + if (!flatObject.hasOwnProperty(x)) continue; - // Set the endpoint URLs, which are the same for all Google services. - .setAuthorizationBaseUrl('https://login.eveonline.com/oauth/authorize/') - .setTokenUrl('https://login.eveonline.com/oauth/token') + toReturn[i + '-' + x] = flatObject[x]; + } + } else { + toReturn[i] = ob[i]; + } + } + return toReturn; +}; + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// OAth2 Functions +// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +function onOpen() { + SpreadsheetApp.getUi().createMenu('GESI') + .addItem('Authorize Sheet', 'showSidebar') + .addSeparator() + .addItem('Reset Auth', 'clearService') + .addToUi(); + +} + +function showSidebar() { + var eveService = createOAuthForUser(AUTHING_CHARACTER); + if (!eveService.hasAccess()) { + var authorizationUrl = eveService.getAuthorizationUrl(); + var template = HtmlService.createTemplate( + '
Authorize: .'); + template.authorizationUrl = authorizationUrl; + template.character = AUTHING_CHARACTER; + var page = template.evaluate(); + SpreadsheetApp.getUi().showSidebar(page); + } +} + +function authCallback(request) { + var eveService = createOAuthForUser(AUTHING_CHARACTER); + var isAuthorized = eveService.handleCallback(request); + if (isAuthorized) { + getCharacterDetails_(); + return HtmlService.createHtmlOutput('Success! You can close this tab.'); + } else { + return HtmlService.createHtmlOutput('Denied. You can close this tab'); + } +} + +function createOAuthForUser(user) { + return OAuth2.createService(user) + .setAuthorizationBaseUrl('https://login.eveonline.com/oauth/authorize/') + .setTokenUrl('https://login.eveonline.com/oauth/token') + .setClientId(CLIENT_ID) + .setClientSecret(CLIENT_SECRET) + .setCallbackFunction('authCallback') + .setPropertyStore(PropertiesService.getUserProperties()) + .setScope('esi-universe.read_structures.v1 esi-wallet.read_corporation_wallets.v1 esi-calendar.read_calendar_events.v1 esi-bookmarks.read_character_bookmarks.v1 esi-contracts.read_character_contracts.v1 esi-industry.read_character_jobs.v1 esi-characters.read_blueprints.v1 esi-markets.read_character_orders.v1 esi-planets.manage_planets.v1 esi-ui.open_window.v1 esi-skills.read_skills.v1 esi-skills.read_skillqueue.v1 esi-markets.structure_markets.v1 esi-characters.read_contacts.v1 esi-assets.read_assets.v1 esi-characters.read_loyalty.v1 esi-wallet.read_character_wallet.v1 esi-ui.write_waypoint.v1') + .setParam('access_type', 'offline') + .setTokenHeaders({ + 'Authorization': 'Basic ' + Utilities.base64Encode(CLIENT_ID + ':' + CLIENT_SECRET) + }) +} + +function clearService() { + for (var i = 0; i < CHARACTERS.length; i++) { + Logger.log(CHARACTERS[i]); + OAuth2.createService(CHARACTERS[i]) + .setPropertyStore(PropertiesService.getUserProperties()) + .reset(); + } +} + +function getCharacterDetails_() { + var userProperties = PropertiesService.getUserProperties(); + var eveService = createOAuthForUser(AUTHING_CHARACTER); + var response = UrlFetchApp.fetch('https://login.eveonline.com/oauth/verify', { + headers: { + Authorization: 'Bearer ' + eveService.getAccessToken() + } + }); + response = JSON.parse(response); + userProperties.setProperty(AUTHING_CHARACTER, response.CharacterID.toString()); +} + +function convertSnakeCase_(headers) { + var formatted_headers = []; + for (var h = 0; h < headers.length; h++) { + str = headers[h].replace(/\_/g, ' '); + formatted_headers.push(str.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + })); + } + return formatted_headers; +} - // Set the client ID and secret, from the EVE Dev site. - .setClientId(CLIENT_ID) - .setClientSecret(CLIENT_SECRET) +function deArrayIndex_(data) { + for (var o = 0; o < data.length; o++) { + for (var a in data[o].cost_indices) { + data[o][data[o].cost_indices[a].activity] = data[o].cost_indices[a].cost_index; + } + delete data[o].cost_indices; + } + return data; +} - // Set the name of the callback function in the script referenced - // above that should be invoked to complete the OAuth flow. - .setCallbackFunction('authCallback') +function characterPlanetDetails_(params, name, opt_headers) { + var planets = new Array(); + if (!name) name = AUTHING_CHARACTER; - // Set the property store where authorized tokens should be persisted. - .setPropertyStore(PropertiesService.getUserProperties()) + var response = getData_('characterPlanetDetails', name, params); - // Set the scopes to request (space-separated). - .setScope('esi-contracts.read_character_contracts.v1 esi-industry.read_character_jobs.v1 esi-characters.read_blueprints.v1 esi-markets.read_character_orders.v1 esi-planets.manage_planets.v1 esi-ui.open_window.v1 esi-skills.read_skills.v1 esi-skills.read_skillqueue.v1 esi-markets.structure_markets.v1 esi-characters.read_contacts.v1 esi-assets.read_assets.v1 esi-characters.read_loyalty.v1 esi-wallet.read_character_wallet.v1 esi-ui.write_waypoint.v1') + // Inserting header for Links + planets.push(['Links']); - // Requests offline access. Allows token to be refreshed when it expires - .setParam('access_type', 'offline') + // Insert data values for links + planets.push(['', 'Source Pin ID', 'Dest Pin ID', 'Link Level']); - .setTokenHeaders({ - 'Authorization': 'Basic ' + Utilities.base64Encode(CLIENT_ID + ':' + CLIENT_SECRET) - }) - } + for (var i = 0; i < response.links.length; i++) { + planets.push([ + '', + response.links[i].source_pin_id, + response.links[i].destination_pin_id, + response.links[i].link_level + ]); + } - function showSidebar() { - var eveService = getEVEService(); - if (!eveService.hasAccess()) { - var authorizationUrl = eveService.getAuthorizationUrl(); - var template = HtmlService.createTemplate( - 'Authorize.'); - template.authorizationUrl = authorizationUrl; - var page = template.evaluate(); - SpreadsheetApp.getUi().showSidebar(page); - } - } + // Inserting header for Pins + planets.push(['Pins']); + + // Insert data values for Pins + planets.push(['', 'Pin ID', 'Type ID', 'Schematic ID', 'Type Id', 'Install Time', 'Last Cycle Start', 'Latitude', 'Longitude']); + + for (var i = 0; i < response.pins.length; i++) { + planets.push([ + '', + response.pins[i].pin_id, + response.pins[i].type_id, + response.pins[i].schematic_id, + response.pins[i].type_id, + response.pins[i].install_time, + response.pins[i].last_cycle_start, + response.pins[i].latitude, + response.pins[i].longitude + ]); + } - function authCallback(request) { - var eveService = getEVEService(); - var isAuthorized = eveService.handleCallback(request); - if (isAuthorized) { - getCharacterDetails_(); - return HtmlService.createHtmlOutput('Success! You can close this tab.'); - } else { - return HtmlService.createHtmlOutput('Denied. You can close this tab'); - } - } + // Inserting header for Extractors + planets.push(['Extractors']); - function clearService() { - OAuth2.createService('EVE') - .setPropertyStore(PropertiesService.getUserProperties()) - .reset(); - } + // Insert data values for Extractors + planets.push(['', 'Pin ID', 'Product Type ID', 'Cycle Time', 'Head Radius', 'Quantity Per Cycle']); - /** - * Returns the active access token. - * @return the active access token. - * @customfunction - */ - function getAccessToken() { - return getEVEService().getAccessToken(); - } + for (var i = 0; i < response.pins.length; i++) { + if (!("extractor_details" in response.pins[i])) { + continue; + } + planets.push(['', + response.pins[i].pin_id, + response.pins[i].extractor_details.product_type_id, + response.pins[i].extractor_details.cycle_time, + response.pins[i].extractor_details.head_radius, + response.pins[i].extractor_details.qty_per_cycle + ]); + } - /** - * Returns details on current endpoints. - * @Returns details on current endpoints. - * @customfunction - */ - function help() { - endpoint_list = []; + // Inserting header for Routes + planets.push(['Routes']); - for(var key in endpoints){ - endpoint_list.push([ - endpoints[key].name, - endpoints[key].description - ]); + // Insert data values for Routes + planets.push(['', 'Route ID', 'Source Pin ID', 'Dest Pin ID', 'Content Type ID', 'Quantity']); - for( var i = 0; i < endpoints[key].parameters.length; i++){ - endpoint_list.push([ - '', - endpoints[key].parameters[i].name, - endpoints[key].parameters[i].description + for (var i = 0; i < response.routes.length; i++) { + planets.push(['', + response.routes[i].route_id, + response.routes[i].source_pin_id, + response.routes[i].destination_pin_id, + response.routes[i].content_type_id, + response.routes[i].quantity ]); - } - - endpoint_list.push(['']); - } - return endpoint_list; - - } - - - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Private Functions - // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - function getData_(endpoint_name, param){ - var userProperties = PropertiesService.getUserProperties(); - var eveService = getEVEService(); - var url = endpoints[endpoint_name].url - - if(url.indexOf('{character_id') !== -1){ url = url.replace('{character_id}', userProperties.getProperty('character_id')); } - if(param != undefined) { url = url.replace(url.match(/{.+}/g)[0], param); } - - var response = UrlFetchApp.fetch(BASE_URL + endpoints[endpoint_name].version + url, { - headers: { - Authorization: 'Bearer ' + eveService.getAccessToken() - } - }); - return response; - } - - function getCharacterDetails_() { - var userProperties = PropertiesService.getUserProperties(); - var eveService = getEVEService(); - var response = UrlFetchApp.fetch('https://login.eveonline.com/oauth/verify', { - headers: { - Authorization: 'Bearer ' + eveService.getAccessToken() - } - }); - response = JSON.parse(response); - var newProperties = { - character_id: response.CharacterID, - characterName: response.CharacterName, - expires: response.ExpiresOn - }; - userProperties.setProperties(newProperties); - } - - function id2name_(ids) { - var unique_ids = ids.filter(function(item, pos) { - return ids.indexOf(item) == pos; - }); - - var options = { - 'method': 'post', - 'contentType': 'application/json', - 'payload': JSON.stringify(unique_ids) - } - var response = UrlFetchApp.fetch('https://esi.tech.ccp.is/v2/universe/names/', options); - return JSON.parse(response); - } - - function capitalize_(string) { - return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); -} \ No newline at end of file + + return planets; +} diff --git a/README.md b/README.md index 84cb397..78056d7 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Modified version of Google's https://github.com/googlesamples/apps-script-oauth2 To request new endpoints/changes/etc create issues or mail me in game (Blacksmoke16). -### Setup: +### Setup for single character use: 1. Create a new google sheet or go to the one you want to use the script on. 2. In the menu bar go to Tools -> Script Editor. 3. Click on the menu item "Resources > Libraries..." @@ -18,84 +18,49 @@ To request new endpoints/changes/etc create issues or mail me in game (Blacksmok * Content Type: Authentication & API Access * PERMISSIONS: Select all ESI endpoints so you wont' have to edit the app each time a new endpoint is added for GESI. * CALLBACK URL: https://script.google.com/macros/d/{SCRIPT_ID_COPIED_IN_STEP_FIVE}/usercallback + * Be sure to replace the `{SCRIPT_ID_COPIED_IN_STEP_FIVE}` in the URL with YOUR script ID! 7. Replace the example CLIENT_ID and CLIENT_SECRET variables towards the top with your info from the dev app, and save. 8. Close the script and refresh the spreadsheet. 9. There will now be a GESI option in the menu bar. Click it and then click 'Authorize Sheet'. 10. Give the script permission to do what it needs. - 11. Click 'Authorize' in the sidenav that opens -> login -> select what character you want to authorize -> Authorize. + 11. Click 'Authorize Sheet' in the sidenav that opens -> login -> select what character you want to authorize -> Authorize. 12. Close the sidenav. 13. Done. - -### Functions: - -##### Note: All functions, unless otherwise stated, have an optional opt_headers parameter that defaults to true and determines if column headers are shown or not. - -##### Global: - * =help() - Returns information on current endpoints. - -##### Skills: - * =skillQueue(opt_headers) - Returns the user's current skill queue. - * =skills(option, opt_headers) - Returns a list of Skill names, current points in skill and current level or total skill points. - * 'List': Returns a list of Skill names, current points in skill and current level - * 'Total': Returns total SP. -##### Market: - * =marketPrices(opt_headers) - Returns the average and adjusted prices for various itemIDs. - * =characterMarketOrders(opt_headers) - Returns a list of market orders placed by a character. - * =structureMarketOrders(structure_id, opt_headers) - Returns all market orders in a given structure. - * structure_id: ID of the structure you want to get market orders from. -##### Universe: - * =itemTypes(ids, opt_headers) - Returns Information about a type. - * ids: Either a single typeID, or a list of typeIDs. - -##### Assets: - * =characterAssets(opt_headers) - Returns a list of the characters assets. - -##### Loyalty: - * =characterLoyalty(opt_headers) - Returns a list of loyalty points for all corporations the character has worked for. - * =corporationLoyalty(corporation_id, opt_headers) - Returns a list of offers from a specific corporation's loyalty store. - * corporation_id: Corporation ID to get the loyalty point store for. - -##### Wallet: - * =characterWallet(opt_headers) - Returns the balance of your wallet. - * =characterWalletJournal(opt_headers) - Returns a character's wallet journal. - * =characterWalletTransactions(opt_headers) - Returns a character's wallet transactions. +### Setup for multiple character use: + 1. Complete steps 1-8 in single character use. + 2. In the script there is a constant variable called `CHARACTERS` (line 13) which is an array of strings. + * Replace the contents of the array with the names of the characters you wish to authorize. + * E.x. `CHARACTERS = ['Blacksmoke16', 'Blacksmoke17', 'Blacksmoke18'];` + 4. To auth the characters: + * In the script there is another constant variable `AUTHING_CHARACTER` (line 15). + * Complete steps 9-13 in single character use. + * Add one (1) to the number in brackets. + * E.x. `AUTHING_CHARACTER = CHARACTERS[1];` + 5. Repeat step 4 until all characters are authorized. + * `AUTHING_CHARACTER = CHARACTERS[1];` -> authorize `Blacksmoke17` using steps 9-13 in single character use. + * `AUTHING_CHARACTER = CHARACTERS[2];` -> authorize `Blacksmoke18` using steps 9-13 in single character use. -##### Planets: - * =characterPlanets(opt_headers) - Returns a list of all planetary colonies owned by a character. - * =characterPlanetDetails(planet_id) - Returns full details on the layout of a single planetary colony, including links, pins and routes. - * planet_id: ID of the planet to get details on. - * =planetSchematic(schematic_id, opt_headers) - Returns information on a planetary factory schematic. - * schematic_id: ID of the schematic to get information on. - -##### Character: - * =characterBlueprints(opt_headers) - Returns a list of blueprints the character has. - -##### Industry: - * =characterIndustryJobs(opt_headers) - Returns a list of industry jobs placed by a character. - * =industryFacilities(opt_headers) - Returns a list of industry facilities. - * =industrySystems(opt_headers) - Returns cost indices for solar systems. - -##### Contracts: - * =characterContracts(opt_headers) - Returns a list of a character's contracts. - * =characterContractBids(contract_id, opt_headers) - Returns bids on a particular auction contract. - * contract_id: ID of the contract to get bids for. - * =characterContractItems(contract_id, opt_headers) -Returns Items and details of a particular contract. - * contract_id: ID of the contract to get information on. - - ##### GESI Dropdown: - * Authorize Sheet - Provides the link to navigate to to login and get your access token - * Reset Auth - Clears the OAuth2 service, making all tokens invalid. - -### Note: In order to use new functions, you will have to re-auth your character. - * Use 'Reset Auth' under GESI dropdown window to clear the old token/auth data. - * Use 'Authorize Sheet' under GESI dropdown window to re-auth your character with the newly added scopes. +### Features for advanced users + +##### To change order of column headers + 1. Find the corresponding object in the ENDPOINTS array. + * E.x. + ``` + "allianceNames": { + "version": 1, + "url": "/alliances/names/", + "headers": ['alliance_id', 'alliance_name'] + } + ``` + 2. Re order the values in the `headers` array to the order you want. + * The value furthest to the left is first + +### Note: In order to use functions that use new scopes, you will have to re-auth your character(s). ### Contact Info In-game: Blacksmoke16 Discord: Blacksmoke16#1684 - -Donations are accepted :) ### Copyright EVE Online and the EVE logo are the registered trademarks of CCP hf. All rights are reserved worldwide. All other