├── src └── index.js ├── deleted.html ├── blocked.html ├── .gitignore ├── flash_embed.html ├── LICENSE ├── package.json ├── index_legacy.html ├── demo_game.html ├── index.html ├── index_iframe.html ├── deleted └── deleted.js ├── README.md ├── blocked └── blocked.js └── Gruntfile.js /src/index.js: -------------------------------------------------------------------------------- 1 | import "@bygd/gd-sdk-pes/dist/default"; -------------------------------------------------------------------------------- /deleted.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Deleted 5 | 6 | 7 | 8 | 9 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Blocked 5 | 9 | 10 | 11 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Folders 2 | lib/ 3 | eslint.html 4 | node_modules/ 5 | .idea/ 6 | OLD/ 7 | .vscode 8 | 9 | # Files 10 | 11 | # Windows image file caches 12 | Thumbs.db 13 | ehthumbs.db 14 | 15 | # Folder config file 16 | Desktop.ini 17 | 18 | # Recycle Bin used on file shares 19 | $RECYCLE.BIN/ 20 | 21 | # Windows Installer files 22 | *.cab 23 | *.msi 24 | *.msm 25 | *.msp 26 | 27 | # ========================= 28 | # Operating System Files 29 | # ========================= 30 | 31 | # OSX 32 | # ========================= 33 | 34 | .DS_Store 35 | .AppleDouble 36 | .LSOverride 37 | 38 | # Icon must ends with two \r. 39 | Icon 40 | 41 | # Thumbnails 42 | ._* 43 | 44 | # Files that might appear on external disk 45 | .Spotlight-V100 46 | .Trashes 47 | 48 | # # It keeps versions having high severity 49 | # package-lock.json 50 | 51 | # temp folder 52 | temp/ 53 | 54 | secrets 55 | temp 56 | package-lock.json -------------------------------------------------------------------------------- /flash_embed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gamedistribution.com HTML5 SDK 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

17 | To view this page ensure that Adobe Flash Player version 18 | 10.0.0 or greater is installed.
19 | Get Adobe Flash player 20 |

21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Gamedistribution.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gamedistribution.com/html5-sdk", 3 | "version": "1.43.34", 4 | "author": "GameDistribution.com", 5 | "description": "GameDistribution.com HTML5 SDK", 6 | "url": "https://gamedistribution.com", 7 | "license": "MIT", 8 | "main": "lib/main.js", 9 | "directories": { 10 | "doc": "https://github.com/GameDistribution/GD-HTML5/wiki" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git@github.com:GameDistribution/GD-HTML5.git" 15 | }, 16 | "dependencies": { 17 | "@bygd/gd-sdk-pes": "1.43.34", 18 | "@popperjs/core": "2.7.2", 19 | "shelljs": "^0.8.5" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.14.6", 23 | "@babel/plugin-transform-runtime": "^7.14.5", 24 | "@babel/preset-env": "^7.14.7", 25 | "babel-loader": "^8.2.2", 26 | "babelify": "^10.0.0", 27 | "grunt": "^1.4.1", 28 | "grunt-banner": "^0.6.0", 29 | "grunt-browser-sync": "^2.2.0", 30 | "grunt-browserify": "^5.3.0", 31 | "grunt-contrib-clean": "^2.0.0", 32 | "grunt-contrib-copy": "^1.0.0", 33 | "grunt-contrib-uglify": "^5.0.1", 34 | "grunt-contrib-watch": "^1.1.0", 35 | "grunt-exec": "^3.0.0", 36 | "grunt-google-cloud": "^1.0.7", 37 | "webpack": "^4.44.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /index_legacy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 53 | 54 | -------------------------------------------------------------------------------- /demo_game.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gamedistribution.com HTML5 SDK 4 | 5 | 10 | 11 | 12 | 13 |
14 | Hello this is my game!
15 | 16 | 17 |

18 |
19 | 20 | 62 | 63 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gamedistribution.com HTML5 SDK 4 | 8 | 33 | 34 | 35 | 36 | 44 |
45 | 46 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /index_iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gamedistribution.com HTML5 Self-Hosted Game Wrapper 5 | 6 | 30 | 31 | 32 | 33 | 76 | 77 | -------------------------------------------------------------------------------- /deleted/deleted.js: -------------------------------------------------------------------------------- 1 | let instance = null; 2 | 3 | /** 4 | * Promo 5 | */ 6 | class Deleted { 7 | /** 8 | * Constructor of SDK Deleted. 9 | * @return {*} 10 | */ 11 | constructor() { 12 | // Make this a singleton. 13 | if (instance) { 14 | return instance; 15 | } else { 16 | instance = this; 17 | } 18 | 19 | // Set a version banner within the developer console. 20 | const banner = console.log( 21 | '%c %c %c This game was deleted, please remove it in your website... ', 22 | 'background: #9854d8', 23 | 'background: #6c2ca7', 'color: #fff; background: #450f78;', 24 | 'background: #6c2ca7', 'background: #9854d8', 25 | 'background: #c4161e; color: #fff;'); 26 | /* eslint-disable */ 27 | console.log.apply(console, banner); 28 | 29 | this.options = { 30 | prefix: 'gdsdk-deleted__', 31 | }; 32 | 33 | this.container = null; 34 | 35 | this.start(); 36 | } 37 | 38 | /** 39 | * start() 40 | * Starts the promo, which is usually called from an ad slot. 41 | */ 42 | start() { 43 | /* eslint-disable */ 44 | const css = ` 45 | .${this.options.prefix} { 46 | box-sizing: border-box; 47 | position: fixed; 48 | z-index: 666; 49 | top: 0; 50 | left: 0; 51 | width: 100%; 52 | height: 100%; 53 | padding: 40px; 54 | overflow: hidden; 55 | background: linear-gradient(0deg, #333, #000); 56 | } 57 | .${this.options.prefix} h1 { 58 | color: #fff; 59 | text-align: center; 60 | text-transform: uppercase; 61 | font-family: Helvetica, Arial, sans-serif; 62 | font-weight: bold; 63 | cursor: pointer; 64 | font-size: 18px; 65 | } 66 | `; 67 | 68 | const html = ` 69 |

This game is offline/ inaccessible on this website

70 | `; 71 | 72 | // Add our styles. 73 | const head = document.head || document.getElementsByTagName('head')[0]; 74 | const style = document.createElement('style'); 75 | style.type = 'text/css'; 76 | style.appendChild(document.createTextNode(css)); 77 | head.appendChild(style); 78 | 79 | // Add our fonts. 80 | const font = document.createElement('link'); 81 | font.type = 'text/css'; 82 | font.rel = 'stylesheet'; 83 | font.href = 'https://fonts.googleapis.com/css?family=Squada+One'; 84 | head.appendChild(font); 85 | 86 | // Add our markup. 87 | this.container = document.createElement('div'); 88 | this.container.innerHTML = html; 89 | this.container.id = this.options.prefix; 90 | this.container.className = this.options.prefix; 91 | this.container.addEventListener('click', () => { 92 | window.open(this.options.url, '_blank'); 93 | }); 94 | const body = document.body || document.getElementsByTagName('body')[0]; 95 | body.insertBefore(this.container, body.firstChild); 96 | } 97 | } 98 | 99 | new Deleted(); 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![npm](https://img.shields.io/npm/v/npm.svg)](https://nodejs.org/) 2 | [![GitHub version](https://img.shields.io/badge/version-1.3.0-green.svg)](https://github.com/GameDistribution/GD-HTML5/) 3 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/GameDistribution/GD-HTML5/blob/master/LICENSE) 4 | 5 | 6 | # Gamedistribution.com HTML5 SDK 7 | This is the documentation of the "GameDistribution.com HTML5 SDK" project. 8 | 9 | Gamedistribution.com is the biggest broker of high quality, cross-platform games. We connect the best game developers to the biggest publishers. 10 | 11 | Running into any issues? Check out the F.A.Q. within the Wiki of the github repository before mailing to support@gamedistribution.com 12 | 13 | ## Implementation within games 14 | The SDK should be integrated within HTML5 games by loading it through our CDN. Specific information of the SDK features and usages can be found at the wiki. 15 | 16 | ### Implementation self-hosted games. 17 | In the case where a developer wants to self-host their game; the SDK should be implemented within the game as aforementioned. The only difference is that they will have to upload a zipped `index.html`-file containing an iframe with the following query variable: `GD_SDK_REFERRER_URL`. The value of this variable should be the parentUrl. A perfect example can be found at `./index_iframe.html`. 18 | 19 | ## Debugging 20 | Games, which include the SDK, can be easily debugged by calling the following from a browser developer console: 21 | ``` 22 | gdsdk.openConsole(); 23 | ``` 24 | The gdsdk namespace is set when creating the SDK instance. We can't change the name of this namespace as it is still used within games using the old SDK implementation. 25 | 26 | ## Repository 27 | The SDK is maintained on a public github repository. 28 | https://github.com/gamedistribution/GD-HTML5 29 | 30 | ## Deployment 31 | Deployment of the SDK to production environments is done through TeamCity. 32 | 33 | ## Installation for development 34 | Install the following programs: 35 | * [NodeJS LTS](https://nodejs.org/). 36 | * [Grunt](http://gruntjs.com/). 37 | 38 | Pull in the rest of the requirements using npm: 39 | ``` 40 | npm install 41 | ``` 42 | 43 | Setup a local node server, watch changes and update your browser view automatically: 44 | ``` 45 | grunt 46 | ``` 47 | 48 | Make a production build: 49 | ``` 50 | grunt build 51 | ``` 52 | 53 | Make a production build of the promotion script. This script is loaded through advertisement slots to support for cross promotions: 54 | ``` 55 | grunt promo 56 | ``` 57 | 58 | ## Events 59 | ### SDK EVENTS 60 | The SDK events should be used by developers to start or pause their game or handling critical errors. Unless the errors are ad related, then they could hook into the AD_ERROR event, however; the SDK should gracefully fail, so this should not be needed. 61 | 62 | | Event | Description | 63 | | --- | --- | 64 | | SDK_READY | When the SDK is ready. | 65 | | SDK_ERROR | When the SDK has hit a critical error. | 66 | | SDK_GAME_START | When the game should start. | 67 | | SDK_GAME_PAUSE | When the game should pause. | 68 | | SDK_GDPR_TRACKING | When the publishers' client has requested to not track his/ her data. Hook into this event to find out if you can record client tracking data. | 69 | | SDK_GDPR_TARGETING | When the publishers' client has requested to not get personalised advertisements. Hook into this event to find out if you can display personalised advertisements in case you use another ad solution. | 70 | | SDK_GDPR_THIRD_PARTY | When the publishers' client has requested to not load third party services. Hook into this event to find out if you can third party services like Facebook, AddThis, and such alike. | 71 | 72 | ### IMA SDK EVENTS 73 | The SDK events are custom ads for handling any thing related to the IMA SDK itself. 74 | 75 | | Event | Description | 76 | | --- | --- | 77 | | AD_SDK_MANAGER_READY | When the adsManager instance is ready with ads. | 78 | | AD_SDK_CANCELED | When the ad is cancelled or stopped because its done running an ad. | 79 | 80 | ### AD EVENTS 81 | The Gamedistribution.com SDK uses the IMA SDK for loading ads. All events of this SDK are also available to the developer. 82 | https://developers.google.com/interactive-media-ads/docs/sdks/html5/ 83 | 84 | | Event | Description | 85 | | --- | --- | 86 | | AD_ERROR | When the ad it self has an error. | 87 | | AD_BREAK_READY | Fired when an ad rule or a VMAP ad break would have played if autoPlayAdBreaks is false. | 88 | | AD_METADATA | Fired when an ads list is loaded. | 89 | | ALL_ADS_COMPLETED | Fired when the ads manager is done playing all the ads. | 90 | | CLICK | Fired when the ad is clicked. | 91 | | COMPLETE | Fired when the ad completes playing. | 92 | | CONTENT_PAUSE_REQUESTED | Fired when content should be paused. This usually happens right before an ad is about to cover the content. | 93 | | CONTENT_RESUME_REQUESTED | Fired when content should be resumed. This usually happens when an ad finishes or collapses. | 94 | | DURATION_CHANGE | Fired when the ad's duration changes. | 95 | | FIRST_QUARTILE | Fired when the ad playhead crosses first quartile. | 96 | | IMPRESSION | Fired when the impression URL has been pinged. | 97 | | INTERACTION | Fired when an ad triggers the interaction callback. Ad interactions contain an interaction ID string in the ad data. | 98 | | LINEAR_CHANGED | Fired when the displayed ad changes from linear to nonlinear, or vice versa. | 99 | | LOADED | Fired when ad data is available. | 100 | | LOG | Fired when a non-fatal error is encountered. The user need not take any action since the SDK will continue with the same or next ad playback depending on the error situation. | 101 | | MIDPOINT | Fired when the ad playhead crosses midpoint. | 102 | | PAUSED | Fired when the ad is paused. | 103 | | RESUMED | Fired when the ad is resumed. | 104 | | SKIPPABLE_STATE_CHANGED | Fired when the displayed ads skippable state is changed. | 105 | | SKIPPED | Fired when the ad is skipped by the user. | 106 | | STARTED | Fired when the ad starts playing. | 107 | | THIRD_QUARTILE | Fired when the ad playhead crosses third quartile. | 108 | | USER_CLOSE | Fired when the ad is closed by the user. | 109 | | VOLUME_CHANGED | Fired when the ad volume has changed. | 110 | | VOLUME_MUTED | Fired when the ad volume has been muted. | 111 | -------------------------------------------------------------------------------- /blocked/blocked.js: -------------------------------------------------------------------------------- 1 | function getQueryParams() { 2 | const params = new URLSearchParams(window.location.search); 3 | return { 4 | domain: params.get('domain'), 5 | id: params.get('id'), 6 | img: params.get('img'), 7 | title: params.get('title'), 8 | unregistered: params.get('unregistered'), 9 | utm_source: params.get('utm_source'), 10 | utm_medium: params.get('utm_medium'), 11 | utm_campaign: params.get('utm_campaign') 12 | }; 13 | } 14 | 15 | let instance = null; 16 | 17 | class Blocked { 18 | /** 19 | * Constructor of SDK Blocked. 20 | * @return {*} 21 | */ 22 | constructor() { 23 | // Make this a singleton. 24 | if (instance) { 25 | return instance; 26 | } else { 27 | instance = this; 28 | } 29 | 30 | const params = getQueryParams(); 31 | 32 | const domain = params.domain || 'gamedistribution.com'; 33 | const gameId = params.id || '49258a0e497c42b5b5d87887f24d27a6'; 34 | const gameImg = params.img || 'https://img.gamedistribution.com/49258a0e497c42b5b5d87887f24d27a6-512x512.jpeg'; 35 | const title = params.title || 'Jewel Burst'; 36 | const unregistered = params.unregistered === 'true' || false; 37 | const utm_source = params.utm_source || domain; 38 | const utm_medium = params.utm_medium || title; 39 | const utm_campaign = params.utm_campaign || "block-and-redirect"; 40 | 41 | // Burada mesajı unregistered'a göre seçiyoruz 42 | let message; 43 | if (unregistered) { 44 | message = '%c %c %c GameDistribution.com BLOCKED! %c %c %c It seems this website has not finished the onboarding process or has not registered to GameDistribution.com. Check on your onboarding process or contact customer support. '; 45 | } else { 46 | message = '%c %c %c GameDistribution.com BLOCKED! %c %c %c This game is not available for this website. '; 47 | } 48 | 49 | // Set a version banner within the developer console. 50 | const banner = console.log( 51 | message, 52 | 'background: #9854d8', 53 | 'background: #6c2ca7', 'color: #fff; background: #450f78;', 54 | 'background: #6c2ca7', 'background: #9854d8', 55 | 'background: #c4161e; color: #fff;' 56 | ); 57 | /* eslint-disable */ 58 | console.log.apply(console, banner); 59 | /* eslint-enable */ 60 | 61 | this.options = { 62 | url: `https://html5.gamedistribution.com/${gameId}/?utm_source=${utm_source}&utm_medium=${utm_medium}&utm_campaign=${utm_campaign}`, 63 | prefix: 'gdsdk-blocked__', 64 | img: gameImg, 65 | title: title, 66 | unregistered: unregistered 67 | }; 68 | 69 | this.container = null; 70 | 71 | this.start(); 72 | } 73 | 74 | /** 75 | * start() 76 | * Starts the promo, which is usually called from an ad slot. 77 | */ 78 | start() { 79 | /* eslint-disable */ 80 | const css = ` 81 | .${this.options.prefix} { 82 | box-sizing: border-box; 83 | position: fixed; 84 | z-index: 666; 85 | top: 0; 86 | left: 0; 87 | width: 100%; 88 | height: 100%; 89 | padding: 40px; 90 | overflow: hidden; 91 | background: linear-gradient(0deg, #333, #000); 92 | display: flex; 93 | flex-direction: column; 94 | justify-content: center; 95 | align-items: center; 96 | } 97 | .${this.options.prefix} h1, 98 | .${this.options.prefix} h2 { 99 | color: #fff; 100 | text-align: center; 101 | text-transform: uppercase; 102 | font-family: Helvetica, Arial, sans-serif; 103 | font-weight: bold; 104 | } 105 | .${this.options.prefix} h1 { 106 | font-size: 18px; 107 | } 108 | .${this.options.prefix} h2 { 109 | font-size: 14px; 110 | font-weight: normal; 111 | } 112 | .${this.options.prefix} a { 113 | color: #fff; 114 | } 115 | .${this.options.prefix} .thumbnail { 116 | width: 150px; 117 | height: 150px; 118 | border-radius: 4px; 119 | background-position: center; 120 | background-size: cover!; 121 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); 122 | background: url("${this.options.img}") 0% 0% / cover; 123 | } 124 | .${this.options.prefix} > .play { 125 | box-sizing: border-box; 126 | z-index: 1; 127 | border: 0; 128 | width: 150px; 129 | padding: 10px 22px; 130 | border-radius: 5px; 131 | border: 3px solid white; 132 | margin: 16px; 133 | background: linear-gradient(0deg, #dddddd, #ffffff); 134 | color: #222; 135 | text-transform: uppercase; 136 | text-shadow: 0 0 1px #fff; 137 | font-family: Helvetica, Arial, sans-serif; 138 | font-size: 18px; 139 | cursor: pointer; 140 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); 141 | -webkit-appearance: button; 142 | -moz-appearance: button; 143 | appearance: button; 144 | 145 | text-decoration: none; 146 | color: initial; 147 | text-align: center; 148 | } 149 | 150 | .${this.options.prefix} > .play:hover { 151 | background: linear-gradient(0deg, #ffffff, #dddddd); 152 | } 153 | .${this.options.prefix} > .play:active { 154 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); 155 | background: linear-gradient(0deg, #ffffff, #f5f5f5); 156 | } 157 | 158 | .${this.options.prefix} a[target="_blank"]::after { 159 | content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==); 160 | margin: 0 3px 0 5px; 161 | } 162 | `; 163 | 164 | // const html = `

The game is blocked for this website.

`; 165 | 166 | let headerText = ` 167 |

${this.options.title} is not available here.

168 |

If you want to play ${this.options.title}, 169 | 170 | Click here to Play 171 | 172 |

`; 173 | 174 | // if (this.options.unregistered === true) { 175 | // headerText = ` 176 | //

${this.options.title} is not available here. 177 | // 178 | // Click here to Play 179 | // 180 | //

181 | //

It seems this website has not finished the onboarding process or has not registered to 182 | // 183 | // Gamedistribution.com. 184 | // 185 | //
186 | //
Please sign up hereor check on your onboarding process. 187 | //

`; 188 | // } 189 | 190 | const html = ` 191 | ${headerText} 192 |
193 |
194 |
195 | 196 | Play 197 | 198 | `; 199 | // Add our styles. 200 | const head = document.head || document.getElementsByTagName('head')[0]; 201 | const style = document.createElement('style'); 202 | style.appendChild(document.createTextNode(css)); 203 | head.appendChild(style); 204 | 205 | // Add our fonts. 206 | const font = document.createElement('link'); 207 | font.type = 'text/css'; 208 | font.rel = 'stylesheet'; 209 | font.href = 'https://fonts.googleapis.com/css?family=Squada+One'; 210 | head.appendChild(font); 211 | 212 | // Add our markup. 213 | this.container = document.createElement('div'); 214 | this.container.innerHTML = html; 215 | this.container.id = this.options.prefix; 216 | this.container.className = this.options.prefix; 217 | // this.container.addEventListener('click', () => { 218 | // window.open(this.options.url, '_blank'); 219 | // }); 220 | const body = document.body || document.getElementsByTagName('body')[0]; 221 | body.insertBefore(this.container, body.firstChild); 222 | } 223 | } 224 | 225 | new Blocked(); 226 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | function atob(str) { 2 | if (str) { 3 | return new Buffer(str, "base64").toString("binary"); 4 | } 5 | return null; 6 | } 7 | 8 | const sh = require('shelljs'); 9 | 10 | const runCmd = (cmd)=>{ 11 | try{ 12 | 13 | const { stdout, stderr, code } = sh.exec(cmd, { silent: true }); 14 | 15 | if(code!==0){ 16 | console.log('Error run cmd!',cmd,code,stderr); 17 | }else{ 18 | console.log('Success run cmd',cmd,code,stdout); 19 | } 20 | 21 | }catch(err){ 22 | console.log('Exception run cmd!',cmd,err); 23 | } 24 | 25 | } 26 | 27 | module.exports = function (grunt) { 28 | const startTS = Date.now(); 29 | 30 | const pkg = grunt.file.readJSON("package.json"); 31 | 32 | grunt.initConfig({ 33 | /** 34 | * This will load in our package.json file so we can have access 35 | * to the project name and appVersion number. 36 | */ 37 | pkg, 38 | 39 | /** 40 | * Copies certain files over from the src folder to the build folder. 41 | */ 42 | copy: { 43 | development: { 44 | expand: true, 45 | flatten: true, 46 | cwd: "./", 47 | src: ["index.html", "blocked.html", "deleted.html"], 48 | dest: "./lib/" 49 | }, 50 | legacy: { 51 | src: ["./lib/main.min.js"], 52 | dest: "./lib/libs/gd/api.js" 53 | } 54 | }, 55 | 56 | /** 57 | * Cleans our build folder. 58 | */ 59 | clean: { 60 | lib: { 61 | src: ["./lib"] 62 | } 63 | }, 64 | 65 | /** 66 | * A code block that will be added to our minified code files. 67 | * Gets the name and appVersion and other info from the above loaded 'package.json' file. 68 | * @example <%= banner.join("\\n") %> 69 | */ 70 | banner: [ 71 | "/*", 72 | "* Project: <%= pkg.name %>", 73 | "* Description: <%= pkg.description %>", 74 | "* Development By: <%= pkg.author %>", 75 | '* Copyright(c): <%= grunt.template.today("yyyy") %>', 76 | '* Version: <%= pkg.version %> (<%= grunt.template.today("dd-mm-yyyy HH:MM") %>)', 77 | "*/" 78 | ], 79 | 80 | /** 81 | * Prepends the banner above to the minified files. 82 | */ 83 | usebanner: { 84 | options: { 85 | position: "top", 86 | banner: '<%= banner.join("\\n") %>', 87 | linebreak: true 88 | }, 89 | files: { 90 | src: ["lib/main.min.js"] 91 | } 92 | }, 93 | 94 | /** 95 | * Browserify is used to support the latest version of javascript. 96 | * We also concat it while we're at it. 97 | * We only use Browserify for the mobile sites. 98 | */ 99 | browserify: { 100 | options: { 101 | transform: [ 102 | [ 103 | "babelify", 104 | { 105 | presets: [ 106 | [ 107 | "@babel/preset-env", 108 | { 109 | debug: false 110 | } 111 | ] 112 | ], 113 | plugins: [["@babel/plugin-transform-runtime"]] 114 | } 115 | ] 116 | ] 117 | }, 118 | lib: { 119 | src: "src/**/*.js", 120 | dest: "lib/main.js" 121 | }, 122 | blocked: { 123 | src: "blocked/blocked.js", 124 | dest: "lib/blocked.js" 125 | }, 126 | deleted: { 127 | src: "deleted/deleted.js", 128 | dest: "lib/deleted.js" 129 | } 130 | }, 131 | 132 | /** 133 | * Do some javascript post processing, like minifying and removing comments. 134 | */ 135 | uglify: { 136 | options: { 137 | position: "top", 138 | linebreak: true, 139 | sourceMap: false, 140 | sourceMapIncludeSources: false, 141 | compress: { 142 | sequences: true, 143 | dead_code: true, 144 | conditionals: true, 145 | booleans: true, 146 | unused: true, 147 | if_return: true, 148 | join_vars: true, 149 | keep_fnames: true 150 | }, 151 | mangle: { 152 | reserved: ['SDKDeprecated'] 153 | }, 154 | beautify: false, 155 | warnings: false 156 | }, 157 | lib: { 158 | src: "lib/main.js", 159 | dest: "lib/main.min.js" 160 | }, 161 | blocked: { 162 | src: "lib/blocked.js", 163 | dest: "lib/blocked.min.js" 164 | }, 165 | deleted: { 166 | src: "lib/deleted.js", 167 | dest: "lib/deleted.min.js" 168 | } 169 | }, 170 | 171 | /** 172 | * Setup a simple watcher. 173 | */ 174 | watch: { 175 | options: { 176 | spawn: false, 177 | debounceDelay: 250 178 | }, 179 | scripts: { 180 | files: ["src/**/*.js", "blocked/**/*.js"], 181 | tasks: ["browserify", "uglify", "duration"] 182 | }, 183 | html: { 184 | files: ["index.html", "blocked.html", "deleted.html"] 185 | }, 186 | grunt: { 187 | files: ["gruntfile.js"] 188 | } 189 | }, 190 | 191 | /** 192 | * Start browser sync, which setups a local node server based on the server root location. 193 | * This task helps with cross browser testing and general workflow. 194 | */ 195 | browserSync: { 196 | bsFiles: { 197 | src: ["lib/", "index.html", "blocked.html", "deleted.html"] 198 | }, 199 | options: { 200 | server: "./", 201 | watchTask: true, 202 | port: 3000 203 | } 204 | } 205 | }); 206 | 207 | // General tasks. 208 | grunt.loadNpmTasks("grunt-exec"); 209 | grunt.loadNpmTasks("grunt-contrib-copy"); 210 | grunt.loadNpmTasks("grunt-contrib-clean"); 211 | grunt.loadNpmTasks("grunt-google-cloud"); 212 | grunt.loadNpmTasks("grunt-browser-sync"); 213 | grunt.loadNpmTasks("grunt-contrib-watch"); 214 | grunt.loadNpmTasks("grunt-browserify"); 215 | grunt.loadNpmTasks("grunt-contrib-uglify"); 216 | grunt.loadNpmTasks("grunt-banner"); 217 | 218 | // Register all tasks. 219 | grunt.registerTask( 220 | "duration", 221 | "Displays the duration of the grunt task up until this point.", 222 | function () { 223 | const date = new Date(Date.now() - startTS); 224 | let hh = date.getUTCHours(); 225 | let mm = date.getUTCMinutes(); 226 | let ss = date.getSeconds(); 227 | if (hh < 10) { 228 | hh = "0" + hh; 229 | } 230 | if (mm < 10) { 231 | mm = "0" + mm; 232 | } 233 | if (ss < 10) { 234 | ss = "0" + ss; 235 | } 236 | console.log("Duration: " + hh + ":" + mm + ":" + ss); 237 | } 238 | ); 239 | grunt.registerTask("sourcemaps", "Build with sourcemaps", function () { 240 | grunt.config.set("uglify.options.sourceMap", true); 241 | grunt.config.set("uglify.options.sourceMapIncludeSources", true); 242 | }); 243 | grunt.registerTask( 244 | "default", 245 | "Start BrowserSync and watch for any changes so we can do live updates while developing.", 246 | function () { 247 | const tasksArray = [ 248 | "copy:development", 249 | "browserify", 250 | "sourcemaps", 251 | "uglify", 252 | "usebanner", 253 | "duration", 254 | "browserSync", 255 | "watch" 256 | ]; 257 | grunt.task.run(tasksArray); 258 | } 259 | ); 260 | grunt.registerTask("build", "Build and optimize the js.", function () { 261 | const tasksArray = [ 262 | "clean", 263 | "browserify", 264 | "uglify", 265 | "usebanner", 266 | "copy:legacy", 267 | "duration" 268 | ]; 269 | grunt.task.run(tasksArray); 270 | }); 271 | grunt.registerTask("buildsync", "Build and optimize the js.", function () { 272 | const tasksArray = [ 273 | "clean", 274 | "browserify", 275 | "uglify", 276 | "usebanner", 277 | "copy:legacy", 278 | "watch" 279 | ]; 280 | grunt.task.run(tasksArray); 281 | }); 282 | grunt.registerTask( 283 | "blocked", 284 | "Build and optimize the blocked js.", 285 | function () { 286 | const tasksArray = [ 287 | "browserify:blocked", 288 | "uglify:blocked", 289 | "duration" 290 | ]; 291 | grunt.task.run(tasksArray); 292 | } 293 | ); 294 | grunt.registerTask( 295 | "deleted", 296 | "Build and optimize the deleted js.", 297 | function () { 298 | const tasksArray = [ 299 | "browserify:deleted", 300 | "uglify:deleted", 301 | "duration" 302 | ]; 303 | grunt.task.run(tasksArray); 304 | } 305 | ); 306 | grunt.registerTask("deploy", "Upload the build files.", function () { 307 | const project = grunt.option("project"), // vooxe-gamedistribution 308 | bucket = grunt.option("bucket"), // gd-sdk-html5 309 | folderIn = grunt.option("in"), // 310 | folderOut = grunt.option("out"); // 311 | 312 | // The key is saved as a system parameter within Team City. 313 | // The service account key of our google cloud account for uploading to 314 | // storage is stringified and then encoded as base64 using btoa() 315 | // console.log(grunt.option('key')); 316 | let keyObj = grunt.option("key"); 317 | let key = JSON.parse(atob(keyObj)); 318 | // console.log(key); 319 | 320 | if (project === undefined) { 321 | grunt.fail.warn("Cannot upload without a project name"); 322 | } 323 | 324 | if (bucket === undefined) { 325 | grunt.fail.warn("OW DEAR GOD THEY ARE STEALING MAH BUCKET!"); 326 | } 327 | 328 | if (key === undefined || key === null) { 329 | grunt.fail.warn("Cannot upload without an auth key"); 330 | } else { 331 | console.log("Key loaded..."); 332 | } 333 | 334 | grunt.config.merge({ 335 | gcs: { 336 | options: { 337 | credentials: key, 338 | project: project, 339 | bucket: bucket, 340 | gzip: true, 341 | metadata: { 342 | "surrogate-key": "gcs" 343 | } 344 | }, 345 | dist: { 346 | cwd: "./lib/", 347 | src: ["**/*"], 348 | dest: "" 349 | } 350 | } 351 | }); 352 | 353 | console.log("Project: " + project); 354 | console.log("Bucket: " + bucket); 355 | 356 | if (folderIn === undefined && folderOut === undefined) { 357 | console.log("Deploying: ./lib/ to gs://" + bucket + "/"); 358 | } else { 359 | if (folderIn !== undefined) { 360 | if (folderOut === undefined) { 361 | grunt.fail.warn('No use in specifying "in" without "out"'); 362 | } 363 | console.log( 364 | "Deploying: ../" + folderIn + " to gs://" + bucket + "/" + folderOut 365 | ); 366 | grunt.config.set("gcs.dist", { 367 | cwd: "../" + folderIn, 368 | src: ["**/*"], 369 | dest: folderOut 370 | }); 371 | } else if (folderOut !== undefined) { 372 | grunt.fail.warn('No use in specifying "out" without "in"'); 373 | } 374 | } 375 | 376 | grunt.task.run("gcs"); 377 | }); 378 | grunt.registerTask( 379 | "archive", 380 | "Upload the build files to version folders.", 381 | function () { 382 | const project = grunt.option("project"), // vooxe-gamedistribution 383 | bucket = grunt.option("bucket"); // gd-sdk-html5 384 | 385 | // The key is saved as a system parameter within Team City. 386 | // The service account key of our google cloud account for uploading to 387 | // storage is stringified and then encoded as base64 using btoa() 388 | // console.log(grunt.option('key')); 389 | let keyObj = grunt.option("key"); 390 | let key = JSON.parse(atob(keyObj)); 391 | // console.log(key); 392 | 393 | if (project === undefined) { 394 | grunt.fail.warn("Cannot upload without a project name"); 395 | } 396 | 397 | if (bucket === undefined) { 398 | grunt.fail.warn("OW DEAR GOD THEY ARE STEALING MAH BUCKET!"); 399 | } 400 | 401 | if (key === undefined || key === null) { 402 | grunt.fail.warn("Cannot upload without an auth key"); 403 | } else { 404 | console.log("Key loaded..."); 405 | } 406 | 407 | grunt.config.merge({ 408 | gcs: { 409 | options: { 410 | credentials: key, 411 | project: project, 412 | bucket: bucket, 413 | gzip: true, 414 | metadata: { 415 | "surrogate-key": "gcs" 416 | } 417 | }, 418 | dist: { 419 | cwd: "./lib/", 420 | src: ["**/*"], 421 | dest: "v/<%= pkg.version %>/" 422 | } 423 | } 424 | }); 425 | 426 | console.log("Project: " + project); 427 | console.log("Bucket: " + bucket); 428 | 429 | console.log("Deploying: ./lib/ to gs://" + bucket + "/"); 430 | 431 | grunt.task.run("gcs"); 432 | } 433 | ); 434 | 435 | grunt.registerTask("deploy-aws","Upload the build files to AWS.",function(){ 436 | console.log('Grunt, running deploy AWS'); 437 | const bucket = grunt.option("bucket"); 438 | if (bucket === undefined) { 439 | grunt.fail.warn("Target bucket not given"); 440 | } 441 | const cmd = `aws s3 sync ./lib s3://${bucket}` 442 | runCmd(cmd); 443 | }); 444 | 445 | grunt.registerTask("archive-aws","Upload the build files to AWS version folders.",function(){ 446 | console.log('Grunt, running archieve AWS'); 447 | const bucket = grunt.option("bucket"); 448 | if (bucket === undefined) { 449 | grunt.fail.warn("Target bucket not given"); 450 | } 451 | const cmd = `aws s3 sync ./lib s3://${bucket}/v/${pkg.version}` 452 | runCmd(cmd); 453 | }); 454 | 455 | }; 456 | --------------------------------------------------------------------------------