Skip to content
This repository has been archived by the owner on Dec 24, 2022. It is now read-only.

Commit

Permalink
Steam privacy settings checkout, code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
cjmaxik committed Mar 16, 2021
1 parent 91f730d commit 26d2a9d
Show file tree
Hide file tree
Showing 16 changed files with 2,540 additions and 2,227 deletions.
Binary file removed media/friends-new.png
Binary file not shown.
Binary file added media/friends.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed media/profile-new.png
Binary file not shown.
Binary file added media/profile-not-registered.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added media/profile-registered.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4,309 changes: 2,202 additions & 2,107 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
"webpack": "^4.36.1",
"webpack-cli": "^3.3.6"
}
}
}
21 changes: 12 additions & 9 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,35 @@

> Chrome / Firefox extension to provide useful information about TruckersMP players in Steam.
![GitHub release (latest by date)](https://img.shields.io/github/v/release/cjmaxik/truckersmp-steam-helper?style=flat-square&label=Release&logo=github) ![Chrome Web Store](https://img.shields.io/chrome-web-store/v/lodcclicinbifbajhlapkolpedcjgbme?label=Chrome&style=flat-square&logo=google-chrome) ![Mozilla Add-on](https://img.shields.io/amo/v/truckersmp-steam-helper@cjmaxik.github.com?label=Firefox&style=flat-square&logo=firefox)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/cjmaxik/truckersmp-steam-helper?style=flat-square&label=Release&logo=github) ![Chrome Web Store](https://img.shields.io/chrome-web-store/v/lodcclicinbifbajhlapkolpedcjgbme?label=Chrome&style=flat-square&logo=google-chrome) ![Mozilla Add-on](https://img.shields.io/amo/v/truckersmp-steam-helper@cjmaxik.github.com?label=Firefox&style=flat-square&logo=firefox)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/cjmaxik/truckersmp-steam-helper/Release?label=Release%20build&style=flat-square) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/cjmaxik/truckersmp-steam-helper/CodeQL?label=CodeQL&style=flat-square)


### [TruckersMP forum topic](https://forum.truckersmp.com/index.php?/topic/102560-truckersmp-steam-helper/)

## Screenshots
*As of the first release*
![Profile](/media/profile-new.png)
![Profile](/media/profile-registered.png)

![Profile](/media/profile-not-registered.png)

![Friends](/media/friends-new.png)
![Friends](/media/friends.png)

## Features
- TruckersMP Info panel in a community profile
- TruckersMP Info panel in Community Profile
- Steam Privacy settings checkout (if no TruckersMP profile found)
- Compact TruckersMP Info in Friends tab (including Pending Invites)
- Various additional settings, including Steam-related

*This extension is inspired by TruckersMP Helper and internal TruckersMP Team tools.*

## Installation
- Google Chrome - [click here](https://chrome.google.com/webstore/detail/truckersmp-steam-helper/lodcclicinbifbajhlapkolpedcjgbme)
- Google Chrome - [click here](https://chrome.google.com/webstore/detail/truckersmp-steam-helper/lodcclicinbifbajhlapkolpedcjgbme)
- Mozilla Firefox - [click here](https://addons.mozilla.org/addon/truckersmp-steam-helper/)

## For Delevopers
Install `Node.js`, run `npm install` in the project's root folder. Use `distribution` folder as the extracted extension path.
Install `Node.js` and `npm`, run `npm install` in the project's root folder.
Use `distribution` folder as the extracted extension path.

Scripts:
- `npm run watch` - for development (you need to update the extension manually to refresh content scripts)
- `npm run build` - for the testing

Expand All @@ -38,4 +41,4 @@ This browser extension is released under [MIT](LICENSE.md) license.
- Federico for the extension template - [fregante/browser-extension-template](https://github.com/fregante/browser-extension-template)
- Handlebars for the template engine - [handlebarsjs.com](https://handlebarsjs.com/)
- Augmented Steam for the inspiration in certain Steam aspects - [tfedor/AugmentedSteam](https://github.com/tfedor/AugmentedSteam)
- TruckersMP Team for the API - [truckersmp.com](https://truckersmp.com) ([privacy policy](https://truckersmp.com/policy))
- TruckersMP Team for the API - [truckersmp.com](https://truckersmp.com) ([privacy policy](https://truckersmp.com/policy))
112 changes: 101 additions & 11 deletions source/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,123 @@ import { readFromCache, removeExpiredItems } from './cache'

// Listeners for a content scripts
browser.runtime.onMessage.addListener((request, _sender) => {
if (request.query === 'player') {
return Promise.resolve(queryPlayer(request))
}
let response = null

switch (request.query) {
case 'player':
response = queryPlayer(request)
break

if (request.query === 'options') {
return Promise.resolve(queryOptions())
case 'options':
response = queryOptions()
break
}

return true
return Promise.resolve(response)
})

/**
* Queue delay
* @param key Index key to delay
* @return {Promise<Function>}
*/
const delay = (key) => new Promise(resolve => setTimeout(resolve, key * 150 + Math.random() * 10))

// Return TruckersMP player data
/**
* Return TruckersMP player data
* @param {Object} request Data object
* @param {String} request.steamId Steam ID
* @param {String} request.key Delay key
* @param {?Boolean} request.withGames Check for games if no TMP profile
* @returns {Object}
*/
const queryPlayer = async (request) => {
return await readFromCache(request.steamId, async function () {
const playerInfo = await readFromCache(request.steamId, async function () {
await delay(request.key)
const response = await fetch('https://api.truckersmp.com/v2/player/' + request.steamId + '?ref=truckersmp-steam-helper')
const response = await fetch(`https://api.truckersmp.com/v2/player/${request.steamId}?ref=truckersmp-steam-helper`)
return await response.json()
})

if ((!playerInfo.data || playerInfo.data.error) && request.withGames) {
playerInfo.games = await queryGames(request)
}

return playerInfo
}

// Return extension options
const queryOptions = async (request) => {
/**
* Return extension options
* @returns {Object}
*/
const queryOptions = async () => {
return await optionsStorage.getAll()
}

/**
* Check user games
* @param {Object} request Data object
* @param {String} request.steamId Steam ID
*/
const queryGames = async (request) => {
const response = await fetch(`https://steamcommunity.com/profiles/${request.steamId}/games/?xml=1`)
const data = await response.text()

const parser = new DOMParser()
const xmlDoc = parser.parseFromString(data, 'text/xml')

const gamesData = xmlDoc.getElementsByTagName('game')

let games = {
ets2: -1,
ats: -1,
all: -1,
count: 0
}

const gamesArray = Array.from(gamesData)
games.count = gamesArray.length
if (!games.count) {
return games
}

gamesArray.forEach((game) => {
// Check for the game existence
const gameID = game.getElementsByTagName('appID')[0].textContent

switch (gameID) {
case '227300':
games.ets2 = 0
break

case '270880':
games.ats = 0
return
}

// Check the game time
const hoursOnRecord = game.getElementsByTagName('hoursOnRecord')[0]
if (hoursOnRecord) {
const gameTime = Number.parseFloat(hoursOnRecord.textContent)

if (['227300', '270880'].includes(gameID)) {
switch (gameID) {
case '227300':
games.ets2 = gameTime
break

case '270880':
games.ats = gameTime
return
}
} else {
games['all'] += gameTime
}
}
})

return games
}

// Cache governor
removeExpiredItems()
browser.alarms.create({ periodInMinutes: 10.0 })
Expand Down
33 changes: 25 additions & 8 deletions source/cache.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
const writeToCache = (steamId, data, timeout) => {
localStorage.setItem(steamId, JSON.stringify({
/**
* Write to cache
* @param {String} key Cache key
* @param {Object} data Data to write
* @param {Number} timeout Cache timeout (in ms)
*/
const writeToCache = (key, data, timeout) => {
localStorage.setItem(key, JSON.stringify({
data,
timeout
}))
}

const readFromCache = async (steamId, callback) => {
const cachedData = JSON.parse(localStorage.getItem(steamId)) || null
const cacheTimeout = Date.now() + 3600 * 1000
/**
* Read from cache
* @param {String} key Cache key (Steam ID by default)
* @param {Function} callback Callback function (if data is not cached)
* @param {?Number} timeout Cache timeout (in minutes)
* @returns {Object}
*/
const readFromCache = async (key, callback, timeout = 60) => {
const cachedData = JSON.parse(localStorage.getItem(key)) || null
const cacheTimeout = Date.now() + timeout * 60 * 1000

// Return cached data
if (cachedData && cachedData.timeout <= cacheTimeout && cachedData.data) {
return cachedData
}

// Execute a callback, put response in a new cache entry
localStorage.removeItem(steamId)
const data = await callback(steamId)
writeToCache(steamId, data, cacheTimeout)
localStorage.removeItem(key)
const data = await callback(key)
writeToCache(key, data, cacheTimeout)

// Return with timeout 0 to indicate an updated value
return {
Expand All @@ -26,6 +39,10 @@ const readFromCache = async (steamId, callback) => {
}
}

/**
* Remove expired items
* Scheduled job
*/
const removeExpiredItems = () => {
const currentDate = Date.now()

Expand Down
24 changes: 18 additions & 6 deletions source/contentScripts/friends.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,32 @@ const init = () => {
})
}

/**
* Insert a warning message
*/
const warningMessage = () => {
const template = `<div class="search_results_none">Due to <img src="${browser.extension.getURL('icons/tmp.png')}" alt="Icon"> API limits, new data might load with a noticeable delay. Be patient 😉 --CJMAXiK</div>`
const titleBarSelector = document.querySelectorAll('div.profile_friends.title_bar')

if (titleBarSelector) titleBarSelector[0].insertAdjacentHTML('beforebegin', template)
}

/**
* Check Steam ID correctness
* @param {String} steamId
* @return {Boolean}
*/
const isSteamId = (steamId) => {
return (steamId && steamId.length === 17 && steamId.startsWith('765611'))
}

/**
* Render the template
* @param {Element} mainSelector
* @param {String} targetSelector
* @param {Function} template
* @param {Number} key
*/
const render = (mainSelector, targetSelector, template, key) => {
const steamId = mainSelector.getAttribute('data-steamid')

Expand All @@ -46,7 +61,8 @@ const render = (mainSelector, targetSelector, template, key) => {
{
query: 'player',
steamId,
key
key,
withGames: false
}
).then((playerInfo) => {
let player = null
Expand All @@ -69,15 +85,11 @@ let lastUrl = location.href
new MutationObserver(() => {
if (location.href !== lastUrl) {
lastUrl = location.href
onUrlChange()
init()
}
}).observe(document, {
subtree: true,
childList: true
})

function onUrlChange () {
init()
}

init()
Loading

0 comments on commit 26d2a9d

Please sign in to comment.