├── .gitattributes ├── web ├── static │ ├── img │ │ ├── games │ │ │ ├── bg │ │ │ │ └── notempty │ │ │ ├── thumb │ │ │ │ └── notempty │ │ │ └── details │ │ │ │ └── notempty │ │ ├── 404.jpg │ │ ├── og_image.png │ │ ├── qr │ │ │ ├── eth.png │ │ │ ├── bitcoin.png │ │ │ ├── monero.png │ │ │ ├── litecoin.png │ │ │ └── bitcoincash.png │ │ ├── favicon-16.png │ │ ├── favicon-32.png │ │ ├── favicon-96.png │ │ ├── drive_tutorial │ │ │ ├── error.png │ │ │ ├── step3.png │ │ │ ├── step6.png │ │ │ ├── step7.png │ │ │ ├── error2.png │ │ │ ├── step1and2.png │ │ │ ├── step4and5.png │ │ │ └── open-all-links.PNG │ │ ├── hoster_logos │ │ │ ├── multiup.png │ │ │ ├── tusfiles.svg │ │ │ ├── magnet.svg │ │ │ ├── zippyshare.svg │ │ │ ├── uptobox.svg │ │ │ ├── uploaded.svg │ │ │ ├── filesupload.svg │ │ │ ├── uploadbuzz.svg │ │ │ ├── megaup.svg │ │ │ ├── sendcm.svg │ │ │ ├── gofile.svg │ │ │ ├── mirrored.svg │ │ │ ├── letsupload.svg │ │ │ ├── userscloud.svg │ │ │ ├── clicknupload.svg │ │ │ ├── krakenfiles.svg │ │ │ ├── downloadgg.svg │ │ │ ├── pixeldrain.svg │ │ │ └── 1fichier.svg │ │ ├── logo.svg │ │ └── logo_sg.svg │ ├── fonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.ttf │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.woff2 │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.eot │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.ttf │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff2 │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.eot │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.ttf │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff2 │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.eot │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.ttf │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.eot │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.ttf │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff2 │ │ ├── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff │ │ └── roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff2 │ ├── css │ │ ├── admin.scss │ │ ├── font-awesome │ │ │ ├── _fixed-width.scss │ │ │ ├── _screen-reader.scss │ │ │ ├── _core.scss │ │ │ ├── _animated.scss │ │ │ ├── _list.scss │ │ │ ├── _larger.scss │ │ │ ├── fontawesome.scss │ │ │ ├── _bordered-pulled.scss │ │ │ ├── _stacked.scss │ │ │ ├── fa-brands.scss │ │ │ ├── fa-solid.scss │ │ │ ├── fa-regular.scss │ │ │ ├── _rotated-flipped.scss │ │ │ └── _mixins.scss │ │ ├── _variables.scss │ │ ├── _easings.scss │ │ ├── _modal.scss │ │ ├── _visualcaptcha.scss │ │ ├── _roboto.scss │ │ ├── _pikaday.scss │ │ ├── _mq.scss │ │ └── _reboot.scss │ └── js │ │ ├── prepend │ │ ├── filesize.min.js │ │ ├── polyfills.js │ │ └── scrollTo.js │ │ └── admin.js └── opensearch.xml ├── .gitignore ├── locale ├── de_DE │ └── LC_MESSAGES │ │ └── messages.mo ├── es_ES │ └── LC_MESSAGES │ │ └── messages.mo └── ru_RU │ └── LC_MESSAGES │ └── messages.mo ├── composer.json ├── db.php ├── README.md ├── templates ├── faq.twig ├── donate.twig ├── 404.twig ├── login.twig ├── rss.twig ├── index.twig ├── imports │ ├── card.twig │ ├── donate.twig │ ├── faq.twig │ └── details.twig ├── queue.twig ├── search.twig ├── pagination.twig ├── drive_tutorial.twig ├── admin.twig ├── main.twig └── game.twig ├── config_blank.php ├── memcached.php ├── twig.ext.php ├── INSTALL.md ├── migrate.php ├── db.sql ├── cron.php └── Elastic.class.php /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /web/static/img/games/bg/notempty: -------------------------------------------------------------------------------- 1 | :D -------------------------------------------------------------------------------- /web/static/img/games/thumb/notempty: -------------------------------------------------------------------------------- 1 | :D -------------------------------------------------------------------------------- /web/static/img/games/details/notempty: -------------------------------------------------------------------------------- 1 | :D -------------------------------------------------------------------------------- /web/static/img/404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/404.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /twig_cache/ 2 | composer.phar 3 | /vendor/ 4 | /config.php 5 | /web/static/img/games/*/*.jpg 6 | -------------------------------------------------------------------------------- /web/static/img/og_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/og_image.png -------------------------------------------------------------------------------- /web/static/img/qr/eth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/qr/eth.png -------------------------------------------------------------------------------- /web/static/img/favicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/favicon-16.png -------------------------------------------------------------------------------- /web/static/img/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/favicon-32.png -------------------------------------------------------------------------------- /web/static/img/favicon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/favicon-96.png -------------------------------------------------------------------------------- /web/static/img/qr/bitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/qr/bitcoin.png -------------------------------------------------------------------------------- /web/static/img/qr/monero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/qr/monero.png -------------------------------------------------------------------------------- /web/static/img/qr/litecoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/qr/litecoin.png -------------------------------------------------------------------------------- /web/static/fonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-brands-400.eot -------------------------------------------------------------------------------- /web/static/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /web/static/fonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-solid-900.eot -------------------------------------------------------------------------------- /web/static/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /web/static/fonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-solid-900.woff -------------------------------------------------------------------------------- /web/static/img/qr/bitcoincash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/qr/bitcoincash.png -------------------------------------------------------------------------------- /locale/de_DE/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/locale/de_DE/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /locale/es_ES/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/locale/es_ES/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /locale/ru_RU/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/locale/ru_RU/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /web/static/fonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-brands-400.woff -------------------------------------------------------------------------------- /web/static/fonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /web/static/fonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-regular-400.eot -------------------------------------------------------------------------------- /web/static/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /web/static/fonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-regular-400.woff -------------------------------------------------------------------------------- /web/static/fonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /web/static/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/error.png -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/step3.png -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/step6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/step6.png -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/step7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/step7.png -------------------------------------------------------------------------------- /web/static/img/hoster_logos/multiup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/hoster_logos/multiup.png -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/error2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/error2.png -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/step1and2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/step1and2.png -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/step4and5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/step4and5.png -------------------------------------------------------------------------------- /web/static/img/drive_tutorial/open-all-links.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/img/drive_tutorial/open-all-links.PNG -------------------------------------------------------------------------------- /web/static/css/admin.scss: -------------------------------------------------------------------------------- 1 | @import 'handsontable'; 2 | @import 'pikaday'; 3 | 4 | #game-edit-table.overflow { 5 | height: 390px; 6 | overflow: hidden; 7 | } -------------------------------------------------------------------------------- /web/static/css/font-awesome/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | text-align: center; 5 | width: (20em / 16); 6 | } 7 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only; } 5 | .sr-only-focusable { @include sr-only-focusable; } 6 | -------------------------------------------------------------------------------- /web/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/tusfiles.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.eot -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.ttf -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff2 -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.eot -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.ttf -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff2 -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.eot -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.ttf -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.eot -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.ttf -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff2 -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff -------------------------------------------------------------------------------- /web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MachineGunnur/GOG-Games/HEAD/web/static/fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff2 -------------------------------------------------------------------------------- /web/static/img/hoster_logos/magnet.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/zippyshare.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/uptobox.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "slim/slim": "3.0", 4 | "slim/twig-view": "^2.3", 5 | "twig/extensions": "^1.5", 6 | "guzzlehttp/guzzle": "^6.3", 7 | "akrabat/rka-ip-address-middleware": "^0.5.0", 8 | "elasticsearch/elasticsearch": "^6.0", 9 | "emotionloop/visualcaptcha": "^0.0.8" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /db.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/filesupload.svg: -------------------------------------------------------------------------------- 1 | cloud-upload-mini -------------------------------------------------------------------------------- /web/static/css/font-awesome/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}, 5 | .fas, 6 | .far, 7 | .fal, 8 | .fab { 9 | -moz-osx-font-smoothing: grayscale; 10 | -webkit-font-smoothing: antialiased; 11 | display: inline-block; 12 | font-style: normal; 13 | font-variant: normal; 14 | text-rendering: auto; 15 | line-height: 1; 16 | } 17 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/_animated.scss: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | animation: fa-spin 2s infinite linear; 6 | } 7 | 8 | .#{$fa-css-prefix}-pulse { 9 | animation: fa-spin 1s infinite steps(8); 10 | } 11 | 12 | @keyframes fa-spin { 13 | 0% { 14 | transform: rotate(0deg); 15 | } 16 | 17 | 100% { 18 | transform: rotate(360deg); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /web/static/js/prepend/filesize.min.js: -------------------------------------------------------------------------------- 1 | // https://github.com/hustcc/filesize.js 2 | !function(i,e){"object"==typeof module&&module.exports?module.exports=e():i.filesize=e()}("undefined"!=typeof window?window:this,function(){var i={iec:"_Ki_Mi_Gi_Ti_Pi_Ei_Zi_Yi",si:"_K_M_G_T_P_E_Z_Y"};return function(e,_,o){e=Math.abs(e),_||0===_||(_=1);var t="si"==o?1e3:1024,n=0;for(i[o]||(o="si");e>=t;)e/=t,++n;return e.toFixed(_)+" "+i[o].split("_")[n]+"B"}}); -------------------------------------------------------------------------------- /web/static/css/font-awesome/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | list-style-type: none; 6 | margin-left: $fa-li-width * 5/4; 7 | padding-left: 0; 8 | 9 | > li { position: relative; } 10 | } 11 | 12 | .#{$fa-css-prefix}-li { 13 | left: -$fa-li-width; 14 | position: absolute; 15 | text-align: center; 16 | width: $fa-li-width; 17 | line-height: inherit; 18 | } 19 | -------------------------------------------------------------------------------- /web/static/img/logo_sg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/uploadbuzz.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/megaup.svg: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | // makes the font 33% larger relative to the icon container 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -.0667em; 9 | } 10 | 11 | .#{$fa-css-prefix}-xs { 12 | font-size: .75em; 13 | } 14 | 15 | .#{$fa-css-prefix}-sm { 16 | font-size: .875em; 17 | } 18 | 19 | @for $i from 1 through 10 { 20 | .#{$fa-css-prefix}-#{$i}x { 21 | font-size: $i * 1em; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/fontawesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com 3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | @import 'mixins'; 7 | @import 'core'; 8 | @import 'larger'; 9 | @import 'fixed-width'; 10 | @import 'list'; 11 | @import 'bordered-pulled'; 12 | @import 'animated'; 13 | @import 'rotated-flipped'; 14 | @import 'stacked'; 15 | @import 'icons'; 16 | @import 'screen-reader'; 17 | -------------------------------------------------------------------------------- /web/opensearch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | GOG Games Search 4 | Search GOG Games 5 | 6 | https://gog-games.com//static/img/favicon-16.png 7 | UTF-8 8 | https://gog-games.com// 9 | 10 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | border: solid .08em $fa-border-color; 6 | border-radius: .1em; 7 | padding: .2em .25em .15em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix}, 14 | .fas, 15 | .far, 16 | .fal, 17 | .fab { 18 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 19 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 20 | } 21 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/sendcm.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | display: inline-block; 6 | height: 2em; 7 | line-height: 2em; 8 | position: relative; 9 | vertical-align: middle; 10 | width: 2em; 11 | } 12 | 13 | .#{$fa-css-prefix}-stack-1x, 14 | .#{$fa-css-prefix}-stack-2x { 15 | left: 0; 16 | position: absolute; 17 | text-align: center; 18 | width: 100%; 19 | } 20 | 21 | .#{$fa-css-prefix}-stack-1x { 22 | line-height: inherit; 23 | } 24 | 25 | .#{$fa-css-prefix}-stack-2x { 26 | font-size: 2em; 27 | } 28 | 29 | .#{$fa-css-prefix}-inverse { 30 | color: $fa-inverse; 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | # GOG Games 6 | A continuitation of Good Old Downloads' [GOG Games](https://github.com/Good-Old-Downloads/gg) project. The goal is to create a copy of the original site by keeping games updated, voting, automated uploading, etc. 7 | 8 | # Authors & Credits 9 | * MachineGunnur 10 | * Lindre - thanks for help friend with english :) 11 | * GOD Team - thanks for giving us site source code on github 12 | 13 | # License 14 | This project is licensed under the GNU General Public License v3.0. See [LICENSE](LICENSE) for details or this [TL;DR](https://tldrlegal.com/license/gnu-general-public-license-v3-(gpl-3)). 15 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/gofile.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/mirrored.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/letsupload.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/fa-brands.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com 3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | 7 | @font-face { 8 | font-family: 'Font Awesome 5 Brands'; 9 | font-style: normal; 10 | font-weight: normal; 11 | src: url('#{$fa-font-path}/fa-brands-400.eot'); 12 | src: url('#{$fa-font-path}/fa-brands-400.eot?#iefix') format('embedded-opentype'), 13 | url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'), 14 | url('#{$fa-font-path}/fa-brands-400.woff') format('woff'), 15 | url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype'), 16 | url('#{$fa-font-path}/fa-brands-400.svg#fontawesome') format('svg'); 17 | } 18 | 19 | .fab { 20 | font-family: 'Font Awesome 5 Brands'; 21 | } 22 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/fa-solid.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com 3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | 7 | @font-face { 8 | font-family: 'Font Awesome 5 Free'; 9 | font-style: normal; 10 | font-weight: 900; 11 | src: url('#{$fa-font-path}/fa-solid-900.eot'); 12 | src: url('#{$fa-font-path}/fa-solid-900.eot?#iefix') format('embedded-opentype'), 13 | url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'), 14 | url('#{$fa-font-path}/fa-solid-900.woff') format('woff'), 15 | url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype'), 16 | url('#{$fa-font-path}/fa-solid-900.svg#fontawesome') format('svg'); 17 | } 18 | 19 | .fa, 20 | .fas { 21 | font-family: 'Font Awesome 5 Free'; 22 | font-weight: 900; 23 | } 24 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/fa-regular.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com 3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | 7 | @font-face { 8 | font-family: 'Font Awesome 5 Free'; 9 | font-style: normal; 10 | font-weight: 400; 11 | src: url('#{$fa-font-path}/fa-regular-400.eot'); 12 | src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'), 13 | url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'), 14 | url('#{$fa-font-path}/fa-regular-400.woff') format('woff'), 15 | url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'), 16 | url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg'); 17 | } 18 | 19 | .far { 20 | font-family: 'Font Awesome 5 Free'; 21 | font-weight: 400; 22 | } 23 | -------------------------------------------------------------------------------- /web/static/css/font-awesome/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | .#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(-1, -1, 2); } 11 | 12 | // Hook for IE8-9 13 | // ------------------------- 14 | 15 | :root { 16 | .#{$fa-css-prefix}-rotate-90, 17 | .#{$fa-css-prefix}-rotate-180, 18 | .#{$fa-css-prefix}-rotate-270, 19 | .#{$fa-css-prefix}-flip-horizontal, 20 | .#{$fa-css-prefix}-flip-vertical { 21 | filter: none; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/userscloud.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/clicknupload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/faq.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block title %}{{ 'FAQ'|trans }}{% endblock title %} 21 | 22 | {% block content %} 23 |
24 | {% include 'imports/faq.twig' %} 25 |
26 | {% endblock content %} 27 | 28 | {% block scripts %} 29 | {% endblock scripts %} -------------------------------------------------------------------------------- /templates/donate.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block title %}{{ 'Donate'|trans }}{% endblock title %} 21 | 22 | {% block content %} 23 |
24 | {% include 'imports/donate.twig' %} 25 |
26 | {% endblock content %} 27 | 28 | {% block scripts %} 29 | {% endblock scripts %} -------------------------------------------------------------------------------- /web/static/img/hoster_logos/krakenfiles.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /templates/404.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | 19 | 20 | 21 | 22 | 404 - Good Old Downloads 23 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /templates/login.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | 19 | {% extends 'main.twig' %} 20 | 21 | {% block title %}{{ 'Login'|trans }}{% endblock title %} 22 | 23 | {% block content %} 24 |
25 |

{{ 'Login'|trans }}

26 |
27 | 28 | 29 | 30 |
31 |
32 | {% endblock content %} 33 | 34 | {% block scripts %} 35 | {% endblock scripts %} -------------------------------------------------------------------------------- /web/static/img/hoster_logos/downloadgg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | icon-logo-download 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /config_blank.php: -------------------------------------------------------------------------------- 1 | 'ayylmaosecretloginpageyolo', 5 | "BASEDIR" => "/var/www/gg", 6 | 7 | // Shows PHP errors, disables the Twig cache, probably does other things. 8 | // Set to false in production. 9 | "DEV" => true, 10 | 11 | // GG has no user system. Set up the login name and password here. 12 | // Again, use a script to change this once in a while if you're paranoid. 13 | "USER" => [ 14 | "NAME" => "supasecretlogin", 15 | "PASS" => "123", 16 | 17 | // Key used with the http API 18 | "KEY" => "123-321-1337" 19 | ], 20 | 21 | // MySQL details 22 | "DB" => [ 23 | "DBHOST" => "localhost", 24 | "DBNAME" => "gg", 25 | "DBUSER" => "root", 26 | "DBPASS" => "123" 27 | ], 28 | 29 | // Memcached details 30 | "MEMCACHED" => [ 31 | "SERVER" => "127.0.0.1", 32 | "PORT" => 11211 33 | ], 34 | 35 | // ElasticSearch details 36 | "ES" => [ 37 | "HOSTS" => [ 38 | "localhost" 39 | ] 40 | ], 41 | 42 | // reCaptcha 43 | "CAPTCHA" => [ 44 | "SECRET" => "", 45 | "SITE" => "", 46 | "TYPE" => "HCAPTCHA" // Can be "RECAPTCHA" or "HCAPTCHA" 47 | ] 48 | ]; 49 | -------------------------------------------------------------------------------- /web/static/js/prepend/polyfills.js: -------------------------------------------------------------------------------- 1 | /* 2 | Polyfill for el.closest() 3 | https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill 4 | */ 5 | if (!Element.prototype.matches) 6 | Element.prototype.matches = Element.prototype.msMatchesSelector || 7 | Element.prototype.webkitMatchesSelector; 8 | 9 | if (!Element.prototype.closest) 10 | Element.prototype.closest = function(s) { 11 | var el = this; 12 | if (!document.documentElement.contains(el)) return null; 13 | do { 14 | if (el.matches(s)) return el; 15 | el = el.parentElement || el.parentNode; 16 | } while (el !== null && el.nodeType === 1); 17 | return null; 18 | }; 19 | 20 | /* 21 | Polyfill for el.matches() 22 | https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill 23 | */ 24 | if (!Element.prototype.matches) { 25 | Element.prototype.matches = 26 | Element.prototype.matchesSelector || 27 | Element.prototype.mozMatchesSelector || 28 | Element.prototype.msMatchesSelector || 29 | Element.prototype.oMatchesSelector || 30 | Element.prototype.webkitMatchesSelector || 31 | function(s) { 32 | var matches = (this.document || this.ownerDocument).querySelectorAll(s), 33 | i = matches.length; 34 | while (--i >= 0 && matches.item(i) !== this) {} 35 | return i > -1; 36 | }; 37 | } -------------------------------------------------------------------------------- /web/static/img/hoster_logos/pixeldrain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/css/_variables.scss: -------------------------------------------------------------------------------- 1 | // Ripped out of Bootstrap 4 2 | 3 | $font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default; 4 | $font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default; 5 | $font-family-base: "Roboto" !default; 6 | 7 | $font-size-base: 14px !default; // Assumes the browser default, typically `16px` 8 | $font-weight-normal: 300 !default; 9 | $font-weight-base: $font-weight-normal !default; 10 | $line-height-base: 1.5 !default; 11 | 12 | $text-muted: rgba(0, 0, 0, 0.45) !default; 13 | 14 | // Body 15 | // 16 | // Settings for the `` element. 17 | 18 | $body-bg: #f9f9f9 !default; 19 | $body-color: #212121 !default; 20 | 21 | 22 | $headings-margin-bottom: 7px !default; 23 | 24 | // Paragraphs 25 | // 26 | // Style p element. 27 | 28 | $paragraph-margin-bottom: 1rem !default; 29 | 30 | // Links 31 | // 32 | // Style anchor elements. 33 | 34 | $link-color: #6a4da5 !default; 35 | $link-decoration: none !default; 36 | $link-hover-color: darken($link-color, 15%) !default; 37 | $link-hover-decoration: underline !default; 38 | 39 | // Tables 40 | // 41 | // Customizes the `.table` component with basic values, each used across all table variations. 42 | 43 | $table-cell-padding: .75rem !default; -------------------------------------------------------------------------------- /web/static/css/font-awesome/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon { 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | display: inline-block; 8 | font-style: normal; 9 | font-variant: normal; 10 | font-weight: normal; 11 | line-height: 1; 12 | vertical-align: -.125em; 13 | } 14 | 15 | @mixin fa-icon-rotate($degrees, $rotation) { 16 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; 17 | transform: rotate($degrees); 18 | } 19 | 20 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 21 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; 22 | transform: scale($horiz, $vert); 23 | } 24 | 25 | 26 | // Only display content to screen readers. A la Bootstrap 4. 27 | // 28 | // See: http://a11yproject.com/posts/how-to-hide-content/ 29 | 30 | @mixin sr-only { 31 | border: 0; 32 | clip: rect(0, 0, 0, 0); 33 | height: 1px; 34 | margin: -1px; 35 | overflow: hidden; 36 | padding: 0; 37 | position: absolute; 38 | width: 1px; 39 | } 40 | 41 | // Use in conjunction with .sr-only to only display content when it's focused. 42 | // 43 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 44 | // 45 | // Credit: HTML5 Boilerplate 46 | 47 | @mixin sr-only-focusable { 48 | &:active, 49 | &:focus { 50 | clip: auto; 51 | height: auto; 52 | margin: 0; 53 | overflow: visible; 54 | position: static; 55 | width: auto; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /templates/rss.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | 19 | 20 | 21 | GOG Games 22 | {{ base_url() }} 23 | Newly added/updated games from GOG-Games.com 24 | en-us 25 | {{ now|date(DATE_RSS) }} 26 | http://blogs.law.harvard.edu/tech/rss 27 | {% for game in games %} 28 | 29 | {{ game.title }} 30 | {{ game.last_update|date(DATE_RSS) }} 31 | 32 | 33 | {{ base_url() }}/game/{{ game.slug }} 34 | {{ game.id }} {{ game.last_update }} 35 | 36 | {% endfor %} 37 | 38 | 39 | -------------------------------------------------------------------------------- /web/static/css/_easings.scss: -------------------------------------------------------------------------------- 1 | $linear : cubic-bezier(0.250, 0.250, 0.750, 0.750); 2 | $ease : cubic-bezier(0.250, 0.100, 0.250, 1.000); 3 | $ease-in : cubic-bezier(0.420, 0.000, 1.000, 1.000); 4 | $ease-out : cubic-bezier(0.000, 0.000, 0.580, 1.000); 5 | $ease-in-out : cubic-bezier(0.420, 0.000, 0.580, 1.000); 6 | 7 | $easeInQuad : cubic-bezier(0.550, 0.085, 0.680, 0.530); 8 | $easeInCubic : cubic-bezier(0.550, 0.055, 0.675, 0.190); 9 | $easeInQuart : cubic-bezier(0.895, 0.030, 0.685, 0.220); 10 | $easeInQuint : cubic-bezier(0.755, 0.050, 0.855, 0.060); 11 | $easeInSine : cubic-bezier(0.470, 0.000, 0.745, 0.715); 12 | $easeInExpo : cubic-bezier(0.950, 0.050, 0.795, 0.035); 13 | $easeInCirc : cubic-bezier(0.600, 0.040, 0.980, 0.335); 14 | $easeInBack : cubic-bezier(0.600, -0.280, 0.735, 0.045); 15 | 16 | $easeOutQuad : cubic-bezier(0.250, 0.460, 0.450, 0.940); 17 | $easeOutCubic : cubic-bezier(0.215, 0.610, 0.355, 1.000); 18 | $easeOutQuart : cubic-bezier(0.165, 0.840, 0.440, 1.000); 19 | $easeOutQuint : cubic-bezier(0.230, 1.000, 0.320, 1.000); 20 | $easeOutSine : cubic-bezier(0.390, 0.575, 0.565, 1.000); 21 | $easeOutExpo : cubic-bezier(0.190, 1.000, 0.220, 1.000); 22 | $easeOutCirc : cubic-bezier(0.075, 0.820, 0.165, 1.000); 23 | $easeOutBack : cubic-bezier(0.175, 0.885, 0.320, 1.275); 24 | 25 | $easeInOutQuad : cubic-bezier(0.455, 0.030, 0.515, 0.955); 26 | $easeInOutCubic : cubic-bezier(0.645, 0.045, 0.355, 1.000); 27 | $easeInOutQuart : cubic-bezier(0.770, 0.000, 0.175, 1.000); 28 | $easeInOutQuint : cubic-bezier(0.860, 0.000, 0.070, 1.000); 29 | $easeInOutSine : cubic-bezier(0.445, 0.050, 0.550, 0.950); 30 | $easeInOutExpo : cubic-bezier(1.000, 0.000, 0.000, 1.000); 31 | $easeInOutCirc : cubic-bezier(0.785, 0.135, 0.150, 0.860); 32 | $easeInOutBack : cubic-bezier(0.680, -0.550, 0.265, 1.550); -------------------------------------------------------------------------------- /memcached.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | try { 21 | if ($CONFIG['DEV']) { 22 | // Use Memcache on windows cause i'm (still) too lazy to set up a VM for this project 23 | if (PHP_OS === "WINNT") { 24 | class MemcacheWrap extends Memcache { 25 | public function set($key, $val, $expire = 0) { 26 | return parent::set($key, $val, 0, $expire); 27 | } 28 | } 29 | $Memcached = new MemcacheWrap(); 30 | $Memcached->connect($CONFIG["MEMCACHED"]["SERVER"], $CONFIG["MEMCACHED"]["PORT"]); 31 | } else { 32 | $Memcached = new Memcached(); 33 | $Memcached->addServer($CONFIG["MEMCACHED"]["SERVER"], $CONFIG["MEMCACHED"]["PORT"]); 34 | } 35 | } else { 36 | $Memcached = new Memcached(); 37 | $Memcached->addServer($CONFIG["MEMCACHED"]["SERVER"], $CONFIG["MEMCACHED"]["PORT"]); 38 | } 39 | } catch (Exception $e) { 40 | echo "Memcached has encountered an error."; 41 | die; 42 | } catch (Error $e) { 43 | echo "Memcached has encountered an error."; 44 | die; 45 | } 46 | -------------------------------------------------------------------------------- /web/static/img/hoster_logos/1fichier.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /templates/index.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block content %} 21 | {% import "imports/card.twig" as card %} 22 | {% include "imports/details.twig" %} 23 | 24 |
25 | {% if notice %} 26 |
27 | {{ notice|raw }} 28 |
29 | {% endif %} 30 |
31 |
32 | 33 | 34 |
35 |
36 | 39 | {% if new != null %} 40 |

{{ 'New Releases'|trans }}

41 |
42 | {{ card.input(new) }} 43 |
44 | {% endif %} 45 | {% if updated != null %} 46 |

{{ 'Updated'|trans }}

47 |
48 | {{ card.input(updated) }} 49 |
50 | {% endif %} 51 |
52 | {% endblock content %} 53 | 54 | {% block scripts %} 55 | {% endblock scripts %} -------------------------------------------------------------------------------- /templates/imports/card.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% macro input(games, elastic) %} 19 | {% if elastic %} 20 | {% set games = games.hits %} 21 | {% endif %} 22 | {% spaceless %} 23 | {% for game in games %} 24 | {% if elastic %} 25 | {% set game_id = game._id %} 26 | {% set game = game._source %} 27 | {% else %} 28 | {% set game_id = game.id %} 29 | {% endif %} 30 | 31 |
32 | 33 |
34 |
35 | {{ game.title }} 36 | {% if game.updated %}{{ 'UPDATED'|trans }}{% endif %} 37 | {% if game.new %}{{ 'NEW'|trans }}{% endif %} 38 | {% if game.indev %}{{ 'IN DEV'|trans }}{% endif %} 39 | {% if game.uploading %}{{ 'UPLOADING'|trans }}{% endif %} 40 |
41 | {% if game.last_update != 0 %} 42 |
43 | {{ 'Last Update:'|trans }} {{ game.last_update|time_diff }} 44 |
45 | {% endif %} 46 |
47 | {% endfor %} 48 | {% endspaceless %} 49 | {% endmacro %} 50 | -------------------------------------------------------------------------------- /templates/imports/donate.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 |

{{ 'Donate'|trans }}

19 | 20 |

{{ 'Do you love this site? Then donate to help keep it alive! So, how can YOU donate?'|trans }}

21 | 22 |
23 | 24 |

{{ 'What are donations used for exactly?'|trans }}

25 |

{{ 'Each donation is used to help cover operating expenses (storage server, seedbox, VPN tunnel and hosting). All games found on this site are archived on a high-speed storage server in a data center. We are currently using over 9TB of storage. We DO NOT profit from any donations.'|trans }}

26 | 27 |

{{ 'What is the total cost to run the site?'|trans }}

28 |

{{ 'Total expenses are €117 (or $129) per month.'|trans }}

29 | 30 |

{{ 'How can I donate?'|trans }}

31 |

{{ 'You may donate via PayPal, credit/debit card, Bitcoin and other cryptocurrencies. See below for more information on each option.'|trans }}

32 | 33 |

{{ 'I want to donate via PayPal, credit/debit card or another cryptocurrency. How may I?'|trans }}

34 |

{{ 'Please send an email to %email% and let us know how you wish to donate and how much and then we will provide more details.'|trans|nl2br|replace({'%email%': 'admin@gog-games.com'})|raw }}

35 | 36 |

{{ 'I have Bitcoin. What is your address?'|trans }}

37 |

{{ 'bc1qp5u3dfw2p3szuneg9rr4d5dunsp7tvwhasm5vs'|trans }}

38 | -------------------------------------------------------------------------------- /web/static/css/_modal.scss: -------------------------------------------------------------------------------- 1 | .modal-state { 2 | display: none; 3 | &:checked { 4 | + .modal { 5 | opacity: 1; 6 | visibility: visible; 7 | .modal__inner { 8 | box-sizing: content-box; 9 | top: 0; 10 | opacity: 1; 11 | } 12 | } 13 | } 14 | } 15 | 16 | .modal { 17 | opacity: 0; 18 | visibility: hidden; 19 | position: fixed; 20 | top: 0; 21 | right: 0; 22 | bottom: 0; 23 | left: 0; 24 | text-align: left; 25 | background: rgba(0,0,0, .5); 26 | transition: opacity 200ms ease; 27 | box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); 28 | z-index: 999; 29 | .modal__bg { 30 | position: absolute; 31 | top: 0; 32 | right: 0; 33 | bottom: 0; 34 | left: 0; 35 | cursor: pointer; 36 | } 37 | .modal__inner { 38 | transition: top 200ms $ease-out, visibility 200ms $ease-out, opacity 200ms $ease-out; 39 | position: absolute; 40 | opacity: 0; 41 | top: 20%; 42 | bottom: 0; 43 | right: 0; 44 | left: 0; 45 | width: 90%; 46 | margin: auto; 47 | overflow: auto; 48 | background: $body-bg; 49 | padding: 25px; 50 | padding-top: 45px; 51 | height: 75%; 52 | border-radius: 4px; 53 | @include mq($from: md) { 54 | left: 50%; 55 | right: auto; 56 | min-width: 750px; 57 | width: auto; 58 | transform: translateX(-50%); 59 | } 60 | &.nopad { 61 | padding-top: 10px; 62 | } 63 | & > h4 { 64 | margin: -35px 0 5px 0; 65 | } 66 | .modal__close { 67 | position: absolute; 68 | right: 0; 69 | top: 0; 70 | padding: 20px; 71 | width: 20px; 72 | height: 20px; 73 | cursor: pointer; 74 | &:after, &:before { 75 | content: ''; 76 | position: absolute; 77 | width: 2px; 78 | height: 1.5em; 79 | background: #ccc; 80 | display: block; 81 | transform: rotate(45deg); 82 | left: 50%; 83 | margin: -3px 0 0 -1px; 84 | top: 10px; 85 | } 86 | &:before { 87 | transform: rotate(-45deg); 88 | } 89 | &:hover { 90 | &:after, &:before { 91 | background: #aaa; 92 | } 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /templates/imports/faq.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 |

{{ 'Frequently Asked Questions'|trans }}

19 |

{{ 'What is the purpose of this site?'|trans }}

20 |

{{ 'Simple! To upload and share games from %goglink%.'|trans|nl2br|replace({'%goglink%': 'GOG.com'})|raw }}

21 |

{{ 'What is the easiest way to download or extract files?'|trans }}

22 |

{{ 'Please use %jdownloader2link% to download game files and %7ziplink% to extract them.'|trans|nl2br|replace({'%jdownloader2link%': 'JDownloader 2', '%7ziplink%': '7-Zip'})|raw }}

23 |

{{ 'Why do I have to complete captcha to view download links?'|trans }}

24 |

{{ 'This is to deter bots from scraping the site and issuing a DMCA takedown on filehosters.'|trans }}

25 |

{{ 'How are download links prevented from expiring?'|trans }}

26 |

{{ 'All games are available to be voted on for a re-upload 60 days after they were last uploaded to guard against dead links.'|trans }}

27 |

{{ 'How can I support the site?'|trans }}

28 |

{{ 'Finding bugs is one way! If you run into any issues or notice anything out of place, please open an issue on %githublink%.'|trans|nl2br|replace({'%githublink%': 'GitHub'})|raw }}

29 |

{{ 'Can I donate?'|trans }}

30 |

{{ 'Yes! %donatelink%.'|trans|nl2br|replace({'%donatelink%': 'Click here to learn more about donating'})|raw }}

31 | -------------------------------------------------------------------------------- /templates/queue.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block title %}{{ 'Upload Queue'|trans }}{% endblock title %} 21 | 22 | {% set queue_starter %} 23 | {% trans %}Here is the list of games currently in the queue. 24 | New games are uploaded first, then updated games, then games ordered by most votes.{% endtrans %} 25 | {% endset %} 26 | 27 | {% block content %} 28 |
29 |

{{ 'Upload Queue'|trans }}

30 |

{{ queue_starter|nl2br }}

31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {% for game in uploading %} 40 | 41 | 42 | 50 | 51 | {% endfor %} 52 | {% for game in new %} 53 | 54 | 55 | 56 | 57 | {% endfor %} 58 | {% for game in updated %} 59 | 60 | 61 | 62 | 63 | {% endfor %} 64 | {% for game in votes %} 65 | 66 | 67 | 68 | 69 | {% endfor %} 70 | 71 |
{{ 'Game'|trans }}{{ 'Type'|trans }}
{{ game.title }} 43 | {% if game.new %} 44 | {{ 'NEW'|trans }} 45 | {% elseif game.updated %} 46 | {{ 'UPDATED'|trans }} 47 | {% endif %} 48 | {{ 'UPLOADING'|trans }} 49 |
{{ game.title }}{{ 'NEW'|trans }}
{{ game.title }}{{ 'UPDATED'|trans }}
{{ game.title }}{{ 'Votes:'|trans }} {{ game.votes }}{% if game.has_voted == 0 %}+{% endif %}
72 |
73 | {% endblock content %} 74 | 75 | {% block scripts %} 76 | {% endblock scripts %} -------------------------------------------------------------------------------- /twig.ext.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | class AppExtension extends \Twig_Extension { 21 | public function getFunctions(){ 22 | return array( 23 | new \Twig_SimpleFunction('loadCSS', array($this, 'loadCSS'), array('is_safe' => array('html'))), 24 | new \Twig_SimpleFunction('loadJS', array($this, 'loadJS'), array('is_safe' => array('html'))), 25 | ); 26 | } 27 | 28 | public function getFilters(){ 29 | return array( 30 | new \Twig_SimpleFilter('long2ip', array($this, 'long2ip')), 31 | new \Twig_SimpleFilter('convertBytes', array($this, 'convertBytes')), 32 | ); 33 | } 34 | 35 | public function long2ip($int){ 36 | return long2ip($int); 37 | } 38 | 39 | public function convertBytes($bytes, $decimals = 2){ 40 | // Jeffrey Sambells 41 | // http://jeffreysambells.com/2012/10/25/human-readable-filesize-php 42 | $size = array('B','KB','MB','GB','TB','PB','EB','ZB','YB'); 43 | $factor = floor((strlen($bytes) - 1) / 3); 44 | return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) .' '. @$size[$factor]; 45 | } 46 | 47 | public function loadCSS($styles, $integrity = null){ 48 | $ret = array(); 49 | if (is_array($styles)) { 50 | foreach ($styles as $key => $value) { 51 | if ($integrity !== null) { 52 | if (!empty($integrity[$key])) { 53 | $integStr = ' integrity="'.$integrity[$key].'"'; 54 | } else { 55 | $integStr = ''; 56 | } 57 | } 58 | if (file_exists(__DIR__.'/web/'.$value)) { 59 | $ret[] = ''; 60 | } 61 | } 62 | } 63 | return join($ret, "\n"); 64 | } 65 | public function loadJS($scripts, $integrity = null){ 66 | $ret = array(); 67 | if (is_array($scripts)) { 68 | foreach ($scripts as $key => $value) { 69 | if ($integrity !== null) { 70 | if (!empty($integrity[$key])) { 71 | $integStr = ' integrity="'.$integrity[$key].'"'; 72 | } else { 73 | $integStr = ''; 74 | } 75 | } 76 | if (file_exists(__DIR__.'/web/'.$value)) { 77 | $ret[] = ''; 78 | } 79 | } 80 | } 81 | return join($ret, "\n"); 82 | } 83 | } -------------------------------------------------------------------------------- /web/static/css/_visualcaptcha.scss: -------------------------------------------------------------------------------- 1 | /*! visualCaptcha - v0.0.8 - 2016-01-23 2 | * http://visualcaptcha.net 3 | * Copyright (c) 2016 emotionLoop; Licensed MIT */ 4 | 5 | /*--------------------------------------------------- 6 | LESS Elements 0.9 7 | --------------------------------------------------- 8 | A set of useful LESS mixins 9 | More info at: http://lesselements.com 10 | ---------------------------------------------------*/ 11 | .visualCaptcha { 12 | min-height: 120px; 13 | } 14 | .visualCaptcha * { 15 | -webkit-box-sizing: border-box; 16 | -moz-box-sizing: border-box; 17 | box-sizing: border-box; 18 | } 19 | .visualCaptcha .audioField { 20 | font-size: 15px; 21 | color: #495e62; 22 | font-weight: 100; 23 | padding: 5px; 24 | border: 1px solid #3bb6e4; 25 | height: 40px; 26 | width: 100%; 27 | -webkit-border-radius: 4px; 28 | -moz-border-radius: 4px; 29 | border-radius: 4px; 30 | } 31 | 32 | .accessibility-description, 33 | .visualCaptcha-explanation, 34 | .status.valid { 35 | padding: 10px; 36 | text-align: center; 37 | font-size: 26px; 38 | font-weight: 100; 39 | margin: 20px 0 24px; 40 | } 41 | .visualCaptcha-possibilities, 42 | .visualCaptcha-refresh-button, 43 | .visualCaptcha-accessibility-button, 44 | .visualCaptcha-button-group { 45 | display: inline-block; 46 | } 47 | .visualCaptcha-possibilities { 48 | vertical-align: middle; 49 | } 50 | .visualCaptcha-possibilities .img { 51 | border: 3px solid transparent; 52 | padding: 5px; 53 | display: inline-block; 54 | } 55 | .visualCaptcha-possibilities img { 56 | width: auto; 57 | height: 45px; 58 | z-index: 5; 59 | transition: all 200ms; 60 | -webkit-transition: all 200ms; 61 | } 62 | .visualCaptcha-possibilities img:hover { 63 | cursor: pointer; 64 | } 65 | .visualCaptcha-possibilities .visualCaptcha-selected { 66 | background-color: #cdbbf0; 67 | border-radius: 4px; 68 | border: 3px dashed #7f4fdb; 69 | } 70 | .visualCaptcha-refresh-button a { 71 | min-width: auto; 72 | } 73 | .visualCaptcha-refresh-button img { 74 | width: 16px; 75 | height: 16px; 76 | } 77 | .visualCaptcha-refresh-button:hover { 78 | cursor: pointer; 79 | } 80 | .visualCaptcha-accessibility-button { 81 | padding: 9px 10px 7px; 82 | border: 1px solid black; 83 | -webkit-border-radius: 100px; 84 | -moz-border-radius: 100px; 85 | border-radius: 100px; 86 | } 87 | .visualCaptcha-accessibility-button img { 88 | width: 16px; 89 | height: 16px; 90 | } 91 | .visualCaptcha-accessibility-button:hover { 92 | cursor: pointer; 93 | } 94 | /* Animations for hiding/showing accessibility option and images */ 95 | @-webkit-keyframes fadeIn { 96 | from { 97 | opacity: 0; 98 | } 99 | to { 100 | opacity: 1; 101 | } 102 | } 103 | @keyframes fadeIn { 104 | from { 105 | opacity: 0; 106 | } 107 | to { 108 | opacity: 1; 109 | } 110 | } 111 | @-webkit-keyframes fadeOut { 112 | from { 113 | opacity: 1; 114 | } 115 | to { 116 | opacity: 0; 117 | } 118 | } 119 | @keyframes fadeOut { 120 | from { 121 | opacity: 1; 122 | } 123 | to { 124 | opacity: 0; 125 | } 126 | } 127 | div.visualCaptcha .visualCaptcha-show { 128 | -webkit-animation: fadeIn 300ms; 129 | animation: fadeIn 300ms; 130 | } 131 | div.visualCaptcha .visualCaptcha-hide { 132 | display: none !important; 133 | -webkit-animation: fadeOut 300ms; 134 | animation: fadeOut 300ms; 135 | } 136 | -------------------------------------------------------------------------------- /templates/search.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block title %}{% if all == false %}{{ term }}{% endif %}{% endblock title %} 21 | 22 | {% block content %} 23 | {% import "imports/card.twig" as card %} 24 | {% include "imports/details.twig" %} 25 | 26 | 77 | {% endblock content %} 78 | 79 | {% block scripts %} 80 | {% endblock scripts %} -------------------------------------------------------------------------------- /web/static/js/prepend/scrollTo.js: -------------------------------------------------------------------------------- 1 | // https://github.com/ericktatsui/scroll-top-pure-js 2 | // Licensed under the MIT License 3 | var scrollTo = function (opt) { 4 | var self, 5 | cache = {}; 6 | 7 | var scrollTo = function () { 8 | self = this; 9 | 10 | this.start = self.getCurrentPosition(); 11 | this.change = self.getNewPosition() - this.start; 12 | this.currentTime = 0; 13 | this.increment = 20; 14 | this.duration = (typeof (opt.duration) === 'undefined') ? 500 : opt.duration; 15 | 16 | if (!this.fail) { 17 | this.animate(); 18 | } 19 | }; 20 | 21 | scrollTo.prototype.animate = function () { 22 | // increment the time 23 | self.currentTime += self.increment; 24 | // find the value with the quadratic in-out easing function 25 | var val = self.easing()(self.currentTime, self.start, self.change, self.duration); 26 | // move the document.body, document.documentElement and window all at once for maximum 27 | document.body.scrollTop = val; 28 | document.documentElement.scrollTop = val; 29 | window.scrollTop = val; 30 | // do the animation unless its over 31 | if (self.currentTime < self.duration) { 32 | self.requestAnimFrame()(self.animate); 33 | } else { 34 | if (opt.callback && typeof (opt.callback) === 'function') { 35 | // the animation is done so lets callback 36 | opt.callback(); 37 | } 38 | } 39 | }; 40 | 41 | scrollTo.prototype.callFail = function () { 42 | self.fail = true; 43 | console.error('Argument is not valid.'); 44 | }; 45 | 46 | scrollTo.prototype.getNewPosition = function () { 47 | var position = 0, 48 | element; 49 | 50 | if (typeof (opt.targetName) == 'string') { 51 | element = document.querySelector(opt.targetName); 52 | 53 | if (element) { 54 | position = (element.getBoundingClientRect()).top + window.scrollY; 55 | } else { 56 | self.callFail(); 57 | } 58 | } else if (typeof (opt.position) == 'number') { 59 | position = opt.position; 60 | } else if (typeof (opt.target) == 'object' && 'getBoundingClientRect' in opt.target) { 61 | position = (opt.target.getBoundingClientRect()).top + window.scrollY; 62 | } else { 63 | self.callFail(); 64 | } 65 | 66 | return position; 67 | }; 68 | 69 | scrollTo.prototype.easing = function () { 70 | var easeType; 71 | 72 | if(!cache.easing){ 73 | switch (opt.easing) { 74 | case 'easeInCubic': 75 | easeType = self.easeInCubic; 76 | break; 77 | case 'inOutQuintic': 78 | easeType = self.inOutQuintic; 79 | break; 80 | default: 81 | easeType = self.easeInOutQuad; 82 | break; 83 | } 84 | 85 | cache.easing = easeType; 86 | }else{ 87 | easeType = cache.easing; 88 | } 89 | 90 | return easeType; 91 | }; 92 | 93 | scrollTo.prototype.easeInOutQuad = function (t, b, c, d) { 94 | t /= d / 2; 95 | if (t < 1) { 96 | return c / 2 * t * t + b 97 | } 98 | t--; 99 | return -c / 2 * (t * (t - 2) - 1) + b; 100 | }; 101 | 102 | scrollTo.prototype.easeInCubic = function (t, b, c, d) { 103 | var tc = (t /= d) * t * t; 104 | return b + c * (tc); 105 | }; 106 | 107 | scrollTo.prototype.inOutQuintic = function (t, b, c, d) { 108 | var ts = (t /= d) * t, 109 | tc = ts * t; 110 | return b + c * (6 * tc * ts + -15 * ts * ts + 10 * tc); 111 | }; 112 | 113 | // polyfill 114 | scrollTo.prototype.requestAnimFrame = function () { 115 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; 116 | }; 117 | 118 | scrollTo.prototype.getCurrentPosition = function () { 119 | return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop; 120 | }; 121 | 122 | return new scrollTo(); 123 | }; -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # GOGGames Installation 2 | 3 | These instructions assume you have experience with installing, configuring, and securing web site software within Linux. Instructions have been tested with Ubuntu 16.04.4 LTS and Debian Stretch. 4 | 5 | That said, it is possible to run GOGGames on a Windows server. 6 | ### Prerequisites 7 | 8 | - PHP >= 7.2 9 | 10 | `apt-get install php` 11 | - MariaDB 12 | 13 | `apt-get install mariadb-server` 14 | - Java or OpenJDK (whichever version that whatever version of ElasticSearch you installed wants) 15 | 16 | `apt-get install openjdk-8-jdk` 17 | - ElasticSearch >= 6.2 18 | 19 | https://www.elastic.co/downloads/elasticsearch 20 | - memcached 21 | 22 | `apt-get install memcached` 23 | - Composer 24 | 25 | https://getcomposer.org/download/ 26 | 27 | ### Installing 28 | ##### Getting the sauce: 29 | 30 | ```bash 31 | git clone https://github.com/Good-Old-Downloads/gg.git 32 | ``` 33 | 34 | ##### Installing the PHP requirements: 35 | `cd` into the directory where the code now lies then install the site dependencies via Composer: 36 | ```bash 37 | cd gg 38 | php composer.phar install 39 | ``` 40 | ##### Configuring the site: 41 | Make a copy of config_blank.php named config.php and edit it. 42 | ```bash 43 | cp config_blank.php config.php 44 | vi config.php 45 | ``` 46 | config.php explantion: 47 | ```php 48 | 'ayylmaosecretloginpageyolo', 52 | "BASEDIR" => "/var/www/gg", 53 | 54 | // Storage paths for GOG iamges 55 | "BG_STORAGE" => "/var/www/gg/static/img/games/bg", 56 | "DETAILS_STORAGE" => "/var/www/god/static/img/games/details", 57 | "THUMB_STORAGE" => "/var/www/god/static/img/games/thumb", 58 | 59 | // Shows PHP errors, disables the Twig cache, probably does other things. 60 | // Set to false in production. 61 | "DEV" => true, 62 | 63 | // GG has no user system. Set up the login name and password here. 64 | // Again, use a script to change this once in a while if you're paranoid. 65 | "USER" => [ 66 | "NAME" => "supasecretlogin", 67 | "PASS" => "123", 68 | 69 | // Key used with the http API 70 | "KEY" => "123-321-1337" 71 | ], 72 | 73 | // MySQL deets 74 | "DB" => [ 75 | "DBNAME" => "gg", 76 | "DBUSER" => "root", 77 | "DBPASS" => "" 78 | ], 79 | 80 | // Memcached deets 81 | "MEMCACHED" => [ 82 | "SERVER" => "127.0.0.1", 83 | "PORT" => 11211 84 | ] 85 | ]; 86 | 87 | // Keys for the Vigenère cipher. Make a lot of these. 88 | // Shitty way to stop the most basic of HTML scrapers, if someone takes time to put the smallest amount of effort decypher this, then they deserve the links. (pretty sure someone from The Eye already made a dumper) 89 | $VKEYS = [ 90 | "RANDKEYONE", 91 | "RANDKEYTWO", 92 | "RANDKEYTHREE", 93 | "RANDKEYFOUR", 94 | "RANDKEYFIVE", 95 | "RANDKEYSIX", 96 | "RANDKESVEN" 97 | ]; 98 | ``` 99 | 100 | ##### Importing the empty database: 101 | Login to MySQL, create a database, then import db.sql. 102 | ``` 103 | MariaDB [(none)]> CREATE DATABASE `gg`; 104 | MariaDB [gg]> USE `gg`; 105 | MariaDB [gg]> SOURCE db.sql; 106 | ``` 107 | 108 | ##### Configuring the Nginx: 109 | The Nginx config is pretty standard. I'll only list the relevant config values. 110 | ```nginx 111 | server { 112 | listen 443 ssl http2; 113 | root /var/www/gg/web; # <-- must point to /web directory 114 | index index.php 115 | autoindex on; 116 | location = /index.php { 117 | try_files $uri =404; 118 | fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; 119 | fastcgi_index index.php; 120 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 121 | include fastcgi_params; 122 | } 123 | location / { 124 | try_files $uri /index.php$is_args$args; 125 | } 126 | location ~ \.php$ { 127 | # prevent exposure of any other .php files!!! 128 | return 404; 129 | } 130 | location ~ /\.ht { 131 | deny all; 132 | } 133 | } 134 | ``` 135 | 136 | ##### Starting up memcached and ElasticSearch: 137 | If you made it this far, you should know how to start these up already, and how to secure them both. 138 | 139 | ### Running tests 140 | lol 141 | 142 | ### Coding style 143 | hahaha 144 | -------------------------------------------------------------------------------- /web/static/css/_roboto.scss: -------------------------------------------------------------------------------- 1 | /* roboto-300 - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */ 2 | @font-face { 3 | font-family: 'Roboto'; 4 | font-style: normal; 5 | font-weight: 300; 6 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.eot'); /* IE9 Compat Modes */ 7 | src: local('Roboto Light'), local('Roboto-Light'), 8 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 9 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff2') format('woff2'), /* Super Modern Browsers */ 10 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff') format('woff'), /* Modern Browsers */ 11 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.ttf') format('truetype'), /* Safari, Android, iOS */ 12 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.svg#Roboto') format('svg'); /* Legacy iOS */ 13 | } 14 | 15 | /* roboto-regular - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */ 16 | @font-face { 17 | font-family: 'Roboto'; 18 | font-style: normal; 19 | font-weight: 400; 20 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.eot'); /* IE9 Compat Modes */ 21 | src: local('Roboto'), local('Roboto-Regular'), 22 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 23 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */ 24 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff') format('woff'), /* Modern Browsers */ 25 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */ 26 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.svg#Roboto') format('svg'); /* Legacy iOS */ 27 | } 28 | 29 | /* roboto-italic - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */ 30 | @font-face { 31 | font-family: 'Roboto'; 32 | font-style: italic; 33 | font-weight: 400; 34 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.eot'); /* IE9 Compat Modes */ 35 | src: local('Roboto Italic'), local('Roboto-Italic'), 36 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 37 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff2') format('woff2'), /* Super Modern Browsers */ 38 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff') format('woff'), /* Modern Browsers */ 39 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.ttf') format('truetype'), /* Safari, Android, iOS */ 40 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.svg#Roboto') format('svg'); /* Legacy iOS */ 41 | } 42 | 43 | /* roboto-500 - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */ 44 | @font-face { 45 | font-family: 'Roboto'; 46 | font-style: normal; 47 | font-weight: 500; 48 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.eot'); /* IE9 Compat Modes */ 49 | src: local('Roboto Medium'), local('Roboto-Medium'), 50 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 51 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff2') format('woff2'), /* Super Modern Browsers */ 52 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff') format('woff'), /* Modern Browsers */ 53 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.ttf') format('truetype'), /* Safari, Android, iOS */ 54 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.svg#Roboto') format('svg'); /* Legacy iOS */ 55 | } 56 | -------------------------------------------------------------------------------- /migrate.php: -------------------------------------------------------------------------------- 1 | prepare("SELECT `game_id`, `files`, `uploading` FROM old_gog.`games_filelist`"); 12 | $get->execute(); 13 | $old_data = $get->fetchAll(\PDO::FETCH_OBJ); 14 | 15 | $getTimes = $dbh->prepare("SELECT `id`, UNIX_TIMESTAMP(`time_upload`) as time_upload, UNIX_TIMESTAMP(`time_update`) as time_update FROM old_gog.`games`"); 16 | $getTimes->execute(); 17 | $times = $getTimes->fetchAll(\PDO::FETCH_OBJ); 18 | 19 | $setTime = $dbh->prepare("UPDATE `games` SET `last_update` = :update, `last_upload` = :upload WHERE `id` = :id"); 20 | $setTime->bindParam(':id', $id, \PDO::PARAM_INT); 21 | $setTime->bindParam(':upload', $upload, \PDO::PARAM_INT); 22 | $setTime->bindParam(':update', $update, \PDO::PARAM_INT); 23 | foreach ($times as $key => $value) { 24 | $id = intval($value->id); 25 | $upload = $value->time_upload; 26 | $update = $value->time_update; 27 | $setTime->execute(); 28 | } 29 | 30 | $getTags = $dbh->prepare("SELECT `id`, `updated`, `new`, `hidden` FROM old_gog.`games`"); 31 | $getTags->execute(); 32 | $tags = $getTags->fetchAll(\PDO::FETCH_OBJ); 33 | 34 | $setTags = $dbh->prepare("UPDATE `games` SET `new` = :new, `updated` = :updated, `hidden` = :hidden WHERE `id` = :id"); 35 | $setTags->bindParam(':id', $id, \PDO::PARAM_INT); 36 | $setTags->bindParam(':new', $new, \PDO::PARAM_INT); 37 | $setTags->bindParam(':updated', $updated, \PDO::PARAM_INT); 38 | $setTags->bindParam(':hidden', $hidden, \PDO::PARAM_INT); 39 | foreach ($tags as $key => $value) { 40 | $id = intval($value->id); 41 | $updated = intval($value->updated); 42 | $new = intval($value->new); 43 | $hidden = intval($value->hidden); 44 | $setTags->execute(); 45 | } 46 | 47 | foreach ($old_data as $key => $value) { 48 | if ($value->uploading == 1) { 49 | continue; 50 | } 51 | $id = intval($value->game_id); 52 | $file_info = json_decode($value->files); 53 | foreach ($file_info as $key => $file) { 54 | switch ($key) { 55 | case 'goodies': 56 | $set = $dbh->prepare("INSERT IGNORE INTO `links` (`game_id`, `link`, `type`) VALUES (:id, :link, 'GOODIES')"); 57 | foreach ($file as $key => $link) { 58 | $set->bindParam(':id', $id, \PDO::PARAM_INT); 59 | $set->bindParam(':link', $link, \PDO::PARAM_STR); 60 | $set->execute(); 61 | } 62 | break; 63 | case 'game': 64 | $set = $dbh->prepare("INSERT IGNORE INTO `links` (`game_id`, `link`, `type`) VALUES (:id, :link, 'GAME')"); 65 | foreach ($file as $key => $link) { 66 | $set->bindParam(':id', $id, \PDO::PARAM_INT); 67 | $set->bindParam(':link', $link, \PDO::PARAM_STR); 68 | $set->execute(); 69 | } 70 | break; 71 | case 'goodies_list': 72 | $set = $dbh->prepare("INSERT IGNORE INTO `files` (`game_id`, `name`, `type`) VALUES (:id, :name, 'GOODIES')"); 73 | foreach ($file as $key => $name) { 74 | $set->bindParam(':id', $id, \PDO::PARAM_INT); 75 | $set->bindParam(':name', $name, \PDO::PARAM_STR); 76 | $set->execute(); 77 | } 78 | break; 79 | case 'game_list': 80 | $set = $dbh->prepare("INSERT IGNORE INTO `files` (`game_id`, `name`, `type`) VALUES (:id, :name, 'GAME')"); 81 | foreach ($file as $key => $name) { 82 | $set->bindParam(':id', $id, \PDO::PARAM_INT); 83 | $set->bindParam(':name', $name, \PDO::PARAM_STR); 84 | $set->execute(); 85 | } 86 | break; 87 | case 'patch_list': 88 | $set = $dbh->prepare("INSERT IGNORE INTO `files` (`game_id`, `name`, `type`) VALUES (:id, :name, 'PATCHES')"); 89 | foreach ($file as $key => $name) { 90 | $set->bindParam(':id', $id, \PDO::PARAM_INT); 91 | $set->bindParam(':name', $name, \PDO::PARAM_STR); 92 | $set->execute(); 93 | } 94 | break; 95 | case 'patch': 96 | $set = $dbh->prepare("INSERT IGNORE INTO `links` (`game_id`, `link`, `type`) VALUES (:id, :link, 'PATCHES')"); 97 | foreach ($file as $key => $link) { 98 | $set->bindParam(':id', $id, \PDO::PARAM_INT); 99 | $set->bindParam(':link', $link, \PDO::PARAM_STR); 100 | $set->execute(); 101 | } 102 | break; 103 | 104 | default: 105 | echo "oh shit\n"; 106 | echo $key; 107 | die; 108 | break; 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /templates/pagination.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | 19 | {# Welcome to hell #} 20 | {# Imported from SG. (it's even worse) #} 21 | {% macro input(pagination, path, adjacents = 2) %} 22 | {% if pagination.page < 1 %} 23 | {% set page = 1 %} 24 | {% else %} 25 | {% set page = pagination.page %} 26 | {% endif %} 27 | 28 | {% set lastpage = (pagination.total/pagination.limit)|round(0, 'ceil') %} 29 | 30 | {% if lastpage <= 0 %} 31 | {% set lastpage = 1 %} 32 | {% endif %} 33 | 34 | {% set prevpage = page - 1 %} 35 | 36 | 99 | {% endmacro %} -------------------------------------------------------------------------------- /templates/drive_tutorial.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block title %}{{ 'Google Drive Quota Exceeded Bypass Tutorial'|trans }}{% endblock title %} 21 | 22 | {% block content %} 23 |
24 |

{{ 'Google Drive Quota Exceeded Bypass Tutorial'|trans }}

25 |

TL;DR: Click the arrow ( ) to open all Google Drive links -> Go to https://drive.google.com/drive/shared-with-me -> Right click and Make a Copy -> Go to My Drive to download the copied file -> Remove file and empty your trash in Google Drive after download to free up cloud storage space to continue for large games.

26 |
27 |

This tutorial will show you how to bypass the Google Drive download limit for files. This does require a Google account. You can get one for free here: https://accounts.google.com/SignUp

28 |

29 | Please be aware: Google has implemented a user quota (or reduced) for the "Make a copy" option this tutorial uses to bypass file download quota. If your trash is empty and you recieve an error when making a copy of a file, you must create a new Google account and continue using the bypass or wait until your "Make a copy" quota resets (unknown amount of time until it resets -- it does seem to reset every day from our testing). 30 |

31 |

This is the error we want to bypass:

32 |

33 | 34 |

35 | 36 |

Steps to bypass:

37 |
    38 |
  1. First you must visit each Google Drive URL in your browser of the file(s) you want to make a copy of. This will make them appear in the "Shared with me" section of your Google Drive. The easiest way to do this with large games is to allow pop-ups for our site, then click the "Open all links" arrow.

  2. 39 |

    40 |
  3. Now go to https://drive.google.com/drive/shared-with-me. You will see the files we visited in the previous step which you can now click and select. If they are not listed, refresh the page and also make sure you have visited the URLs in your browser (see previous step)!

  4. 41 |
  5. Next right click while your files are selected and choose MAKE A COPY from the drop down menu. DO NOT SELECT DOWNLOAD. 42 |

    Please note that free Google accounts only have 15GB of cloud storage.
    43 |
    If a game is very large, you will have to download then remove the parts of the game you made a copy of from your Google Drive and repeat these steps (see step 7 and 8 on how to remove and delete files from your Google Drive) until you have all required files downloaded to install the game!

  6. 44 |

    45 |
  7. Next click "My Drive" found on the left hand side.

  8. 46 |
  9. The items can now be found in your Google Drive.

  10. 47 |
  11. Right click on the item you want to download, then select "Download" in the drop down menu. 48 |
    For larger files, we recommend you download each one individually as Google will take time to zip the files if you select them all and try to download.

  12. 49 |
  13. After your download finishes, you should remove the copies from your Google Drive to free up space in the event you need to do this bypass again (or need to copy and download additional files for larger games). 50 |
    You can do this by selecting the copies you want to delete, then right click and select "Remove" at the bottom of the drop down menu.

  14. 51 |
  15. Finally delete the copies from your trash. Click "Trash" found on the left hand side then click the "Trash" at the top and select "Empty Trash".

  16. 52 |
53 |
54 | {% endblock content %} 55 | 56 | {% block scripts %} 57 | {% endblock scripts %} -------------------------------------------------------------------------------- /templates/admin.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block title %}{{ 'Administration'|trans }}{% endblock title %} 21 | {% block meta %}{{ loadCSS(['/static/css/admin.css'], []) }}{% endblock meta %} 22 | {% block content %} 23 |
24 |

{{ 'Administration '|trans }}

25 |

{{ 'Batch Tag Games:'|trans }}

26 |
27 | 28 | 29 | 36 | 37 |
38 |
39 |

Elasticsearch:

40 |
41 | 42 |
43 |
44 | 45 |
46 |
47 |

{{ 'Edit Database:'|trans }}

48 |
49 | 55 | 56 | 57 | 58 |

0 unsaved changes.

59 |
60 |
61 | {% trans %}{{ game_amount }} games, {{ game_hidden_amount }} hidden, {{ game_new_amount }} new, {{ game_updated_amount }} updated, {{ game_total_amount }} total.{% endtrans %} 62 |
63 |

{{ 'Update Database:'|trans }}

64 | 65 | 66 |
67 |

{{ 'Add game via Product ID:'|trans }}

68 |
69 | 70 | 71 |
72 |
73 |

{{ 'Log:'|trans }}

74 | 75 |
76 |

{{ 'Edit Site Notice:'|trans }}

77 |
78 | 79 | 80 |
81 |
82 |

{{ 'Donation Tracker:'|trans }}

83 |

Monthly donation tracker.

84 |
85 | Amount: 86 | Goal: 87 | 88 |
89 |
90 |

{{ 'Edit Hosters:'|trans }}

91 |

Have to change host column in files table if id is changed.

92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | {% for host in hosters %} 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | {% endfor %} 112 | 113 |
idnameordericon_html
{{ host.id }}{{ host.name }}{{ host.order }}{{ host.icon_html }}
114 |
115 | {% endblock content %} 116 | 117 | {% block scripts %} 118 | {{ loadJS(['/static/js/Sortable.min.js'], []) }} 119 | {{ loadJS(['/static/js/pikaday.js'], []) }} 120 | {{ loadJS(['/static/js/handsontable.min.js'], []) }} 121 | {{ loadJS(['/static/js/admin.js'], []) }} 122 | {% endblock scripts %} 123 | -------------------------------------------------------------------------------- /db.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS `files` ( 2 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 3 | `game_id` int(10) unsigned DEFAULT 0, 4 | `name` varchar(255) NOT NULL DEFAULT '0', 5 | `type` enum('GAME','GOODIES','PATCHES') NOT NULL, 6 | `size` bigint(20) unsigned DEFAULT NULL, 7 | PRIMARY KEY (`id`), 8 | KEY `type` (`type`), 9 | KEY `name` (`name`), 10 | KEY `game_id` (`game_id`), 11 | KEY `size` (`size`) 12 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 13 | 14 | CREATE TABLE IF NOT EXISTS `games` ( 15 | `id` int(11) unsigned NOT NULL, 16 | `title` varchar(255) NOT NULL, 17 | `indev` tinyint(1) unsigned NOT NULL DEFAULT 0, 18 | `new` tinyint(1) unsigned NOT NULL DEFAULT 0, 19 | `updated` tinyint(1) unsigned NOT NULL DEFAULT 0, 20 | `last_upload` int(11) unsigned NOT NULL DEFAULT 0, 21 | `last_update` int(11) unsigned NOT NULL DEFAULT 0, 22 | `thumb_id` varchar(64) DEFAULT NULL, 23 | `bg_id` varchar(64) DEFAULT NULL, 24 | `slug` varchar(255) NOT NULL, 25 | `slug_folder` varchar(255) DEFAULT NULL, 26 | `url` varchar(2083) DEFAULT NULL, 27 | `release_date` int(11) unsigned DEFAULT NULL, 28 | `developer` varchar(255) DEFAULT NULL, 29 | `publisher` varchar(255) DEFAULT NULL, 30 | `category` varchar(255) DEFAULT NULL, 31 | `hidden` tinyint(1) unsigned NOT NULL DEFAULT 0, 32 | `uploading` tinyint(1) unsigned NOT NULL DEFAULT 0, 33 | `queued` tinyint(1) unsigned NOT NULL DEFAULT 0, 34 | PRIMARY KEY (`id`), 35 | UNIQUE KEY `unq_slug` (`slug`), 36 | UNIQUE KEY `unq_slug_folder` (`slug_folder`), 37 | KEY `cat` (`category`), 38 | KEY `pub` (`publisher`), 39 | KEY `dev` (`developer`), 40 | KEY `slug` (`slug`), 41 | KEY `rlsdate` (`release_date`), 42 | KEY `hidden` (`hidden`), 43 | KEY `indev` (`indev`), 44 | KEY `new` (`new`), 45 | KEY `updated` (`updated`), 46 | KEY `title` (`title`), 47 | KEY `last_upload` (`last_upload`), 48 | KEY `date_added` (`last_update`), 49 | KEY `slug_folder` (`slug_folder`), 50 | KEY `uploading` (`uploading`), 51 | KEY `queued` (`queued`), 52 | KEY `thumb_id` (`thumb_id`), 53 | KEY `bg_id` (`bg_id`) 54 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 55 | 56 | CREATE TABLE IF NOT EXISTS `hosters` ( 57 | `id` varchar(50) NOT NULL, 58 | `name` varchar(50) NOT NULL, 59 | `order` int(2) unsigned NOT NULL, 60 | `icon_html` text DEFAULT NULL, 61 | PRIMARY KEY (`id`), 62 | KEY `order` (`order`) 63 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 64 | 65 | INSERT INTO `hosters` (`id`, `name`, `order`, `icon_html`) VALUES 66 | ('1fichier', '1fichier', 14, ''), 67 | ('filecloud', 'filecloud.io', 8, ''), 68 | ('filescdn', 'Filescdn', 9, ''), 69 | ('gdrive', 'Google Drive', 2, ''), 70 | ('gdrive_folder', 'Google Drive', 1, ''), 71 | ('letsupload', 'LetsUpload', 3, ''), 72 | ('megaup', 'MegaUp', 5, ''), 73 | ('openload', 'Openload', 7, ''), 74 | ('shareonline_biz', 'Share-Online', 13, ''), 75 | ('uploaded', 'Uploaded.net', 12, ''), 76 | ('uploadhaven', 'UploadHaven', 4, ''), 77 | ('uptobox', 'UptoBox', 11, ''), 78 | ('userscloud', 'Userscloud', 6, ''), 79 | ('zippyshare', 'Zippyshare', 10, ''); 80 | 81 | 82 | CREATE TABLE IF NOT EXISTS `links` ( 83 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 84 | `game_id` int(10) unsigned DEFAULT 0, 85 | `link` varchar(255) NOT NULL DEFAULT '0', 86 | `link_safe` varchar(255) DEFAULT NULL, 87 | `name` varchar(255) DEFAULT NULL, 88 | `type` enum('GAME','GOODIES','PATCHES') NOT NULL, 89 | `host` varchar(50) DEFAULT NULL, 90 | `hidden` tinyint(1) unsigned NOT NULL DEFAULT 0, 91 | PRIMARY KEY (`id`), 92 | KEY `type` (`type`), 93 | KEY `game_id` (`game_id`), 94 | KEY `link` (`link`), 95 | KEY `name` (`name`), 96 | KEY `host` (`host`), 97 | KEY `hidden` (`hidden`), 98 | KEY `link_safe` (`link_safe`) 99 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 100 | 101 | CREATE TABLE IF NOT EXISTS `log` ( 102 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 103 | `value` text DEFAULT NULL, 104 | `date` int(11) unsigned NOT NULL, 105 | PRIMARY KEY (`id`) 106 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 107 | 108 | CREATE TABLE IF NOT EXISTS `site` ( 109 | `name` varchar(100) NOT NULL, 110 | `value` text DEFAULT NULL, 111 | PRIMARY KEY (`name`) 112 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 113 | 114 | CREATE TABLE IF NOT EXISTS `votes` ( 115 | `uid` varbinary(16) NOT NULL, 116 | `game_id` int(11) NOT NULL, 117 | PRIMARY KEY (`uid`,`game_id`) 118 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /web/static/css/_pikaday.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Pikaday 3 | * Copyright © 2014 David Bushell | BSD & MIT license | http://dbushell.com/ 4 | */ 5 | 6 | // Variables 7 | // Declare any of these variables before importing this SCSS file to easily override defaults 8 | // Variables are namespaced with the pd (pikaday) prefix 9 | 10 | // Colours 11 | $pd-text-color: #333 !default; 12 | $pd-title-color: #333 !default; 13 | $pd-title-bg: #fff !default; 14 | $pd-picker-bg: #fff !default; 15 | $pd-picker-border: #ccc !default; 16 | $pd-picker-border-bottom: #bbb !default; 17 | $pd-picker-shadow: rgba(0,0,0,.5) !default; 18 | $pd-th-color: #999 !default; 19 | $pd-day-color: #666 !default; 20 | $pd-day-bg: #f5f5f5 !default; 21 | $pd-day-hover-color: #fff !default; 22 | $pd-day-hover-bg: #ff8000 !default; 23 | $pd-day-today-color: #33aaff !default; 24 | $pd-day-selected-color: #fff !default; 25 | $pd-day-selected-bg: #33aaff !default; 26 | $pd-day-selected-shadow: #178fe5 !default; 27 | $pd-day-disabled-color: #999 !default; 28 | $pd-week-color: #999 !default; 29 | 30 | // Font 31 | $pd-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !default; 32 | 33 | 34 | .pika-single { 35 | z-index: 9999; 36 | display: block; 37 | position: relative; 38 | color: $pd-text-color; 39 | background: $pd-picker-bg; 40 | border: 1px solid $pd-picker-border; 41 | border-bottom-color: $pd-picker-border-bottom; 42 | font-family: $pd-font-family; 43 | 44 | &.is-hidden { 45 | display: none; 46 | } 47 | 48 | &.is-bound { 49 | position: absolute; 50 | box-shadow: 0 5px 15px -5px $pd-picker-shadow; 51 | } 52 | } 53 | 54 | // clear child float (pika-lendar), using the famous micro clearfix hack 55 | // http://nicolasgallagher.com/micro-clearfix-hack/ 56 | .pika-single { 57 | *zoom: 1; 58 | 59 | &:before, 60 | &:after { 61 | content: " "; 62 | display: table; 63 | } 64 | 65 | &:after { clear: both } 66 | } 67 | 68 | .pika-lendar { 69 | float: left; 70 | width: 240px; 71 | margin: 8px; 72 | } 73 | 74 | .pika-title { 75 | position: relative; 76 | text-align: center; 77 | 78 | select { 79 | cursor: pointer; 80 | position: absolute; 81 | z-index: 9998; 82 | margin: 0; 83 | left: 0; 84 | top: 5px; 85 | filter: alpha(opacity=0); 86 | opacity: 0; 87 | } 88 | } 89 | 90 | .pika-label { 91 | display: inline-block; 92 | *display: inline; 93 | position: relative; 94 | z-index: 9999; 95 | overflow: hidden; 96 | margin: 0; 97 | padding: 5px 3px; 98 | font-size: 14px; 99 | line-height: 20px; 100 | font-weight: bold; 101 | color: $pd-title-color; 102 | background-color: $pd-title-bg; 103 | } 104 | 105 | .pika-prev, 106 | .pika-next { 107 | display: block; 108 | cursor: pointer; 109 | position: relative; 110 | outline: none; 111 | border: 0; 112 | padding: 0; 113 | width: 20px; 114 | height: 30px; 115 | text-indent: 20px; // hide text using text-indent trick, using width value (it's enough) 116 | white-space: nowrap; 117 | overflow: hidden; 118 | background-color: transparent; 119 | background-position: center center; 120 | background-repeat: no-repeat; 121 | background-size: 75% 75%; 122 | opacity: .5; 123 | *position: absolute; 124 | *top: 0; 125 | 126 | &:hover { 127 | opacity: 1; 128 | } 129 | 130 | &.is-disabled { 131 | cursor: default; 132 | opacity: .2; 133 | } 134 | } 135 | 136 | .pika-prev, 137 | .is-rtl .pika-next { 138 | float: left; 139 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg=='); 140 | *left: 0; 141 | } 142 | 143 | .pika-next, 144 | .is-rtl .pika-prev { 145 | float: right; 146 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII='); 147 | *right: 0; 148 | } 149 | 150 | .pika-select { 151 | display: inline-block; 152 | *display: inline; 153 | } 154 | 155 | .pika-table { 156 | width: 100%; 157 | border-collapse: collapse; 158 | border-spacing: 0; 159 | border: 0; 160 | 161 | th, 162 | td { 163 | width: 14.285714285714286%; 164 | padding: 0; 165 | } 166 | 167 | th { 168 | color: $pd-th-color; 169 | font-size: 12px; 170 | line-height: 25px; 171 | font-weight: bold; 172 | text-align: center; 173 | } 174 | 175 | abbr { 176 | border-bottom: none; 177 | cursor: help; 178 | } 179 | } 180 | 181 | .pika-button { 182 | cursor: pointer; 183 | display: block; 184 | -moz-box-sizing: border-box; 185 | box-sizing: border-box; 186 | outline: none; 187 | border: 0; 188 | margin: 0; 189 | width: 100%; 190 | padding: 5px; 191 | color: $pd-day-color; 192 | font-size: 12px; 193 | line-height: 15px; 194 | text-align: right; 195 | background: $pd-day-bg; 196 | 197 | .is-today & { 198 | color: $pd-day-today-color; 199 | font-weight: bold; 200 | } 201 | 202 | .is-selected & { 203 | color: $pd-day-selected-color; 204 | font-weight: bold; 205 | background: $pd-day-selected-bg; 206 | box-shadow: inset 0 1px 3px $pd-day-selected-shadow; 207 | border-radius: 3px; 208 | } 209 | 210 | .is-disabled &, 211 | .is-outside-current-month & { 212 | color: $pd-day-disabled-color; 213 | opacity: .3; 214 | } 215 | 216 | .is-disabled & { 217 | pointer-events: none; 218 | cursor: default; 219 | } 220 | 221 | &:hover { 222 | color: $pd-day-hover-color; 223 | background: $pd-day-hover-bg; 224 | box-shadow: none; 225 | border-radius: 3px; 226 | } 227 | 228 | .is-selection-disabled { 229 | pointer-events: none; 230 | cursor: default; 231 | } 232 | } 233 | 234 | .pika-week { 235 | font-size: 11px; 236 | color: $pd-week-color; 237 | } 238 | 239 | .is-inrange .pika-button { 240 | background: #D5E9F7; 241 | } 242 | 243 | .is-startrange .pika-button { 244 | color: #fff; 245 | background: #6CB31D; 246 | box-shadow: none; 247 | border-radius: 3px; 248 | } 249 | 250 | .is-endrange .pika-button { 251 | color: #fff; 252 | background: #33aaff; 253 | box-shadow: none; 254 | border-radius: 3px; 255 | } -------------------------------------------------------------------------------- /templates/main.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | 19 | {% set baseUrl = base_url()|replace({'http://': '', 'https://': ''}) %} 20 | {% if base_url()|slice(0, 5) == "http:" %} 21 | {% set urlScheme = "http://" %} 22 | {% elseif base_url()|slice(0, 5) == "https" %} 23 | {% set urlScheme = "https://" %} 24 | {% endif %} 25 | 26 | 27 | 28 | 29 | 30 | 31 | {% block title %}{% endblock title %}{% if block('title') is defined and block('title') != '' %} - {% endif %}GOG Games | Download Free GOG PC Games 32 | 33 | 34 | 35 | 36 | 37 | 38 | {{ loadCSS(['/static/css/style.css'], []) }} 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | {% block meta %} 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {% endblock meta %} 55 | 59 | 60 | 61 | 62 | {# FAQ Modal #} 63 | 64 | 71 | 72 | {# Donate Modal #} 73 | 74 | 81 | 82 | {# Captcha Modal #} 83 | 84 | 98 | 99 | 122 | 123 | {% block content %}{% endblock content %} 124 | {% if was_user and session.user == config.USER.NAME %} 125 | 128 | {% endif %} 129 | {{ loadJS(['/static/js/moment-with-locales.js'], []) }} 130 | {% if language %} 131 | 132 | {% endif %} 133 | 134 | {{ loadJS(['/static/js/main.min.js'], []) }} 135 | {% block scripts %}{% endblock scripts %} 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /cron.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | if (php_sapi_name() !== 'cli') { 21 | echo "Only run from command line!"; 22 | die; 23 | } 24 | ini_set('max_execution_time', 2400); 25 | require 'vendor/autoload.php'; 26 | require 'config.php'; 27 | require 'db.php'; 28 | require 'Elastic.class.php'; 29 | 30 | function addLog($text){ 31 | global $dbh; 32 | $now = date('U'); 33 | 34 | // Prepare SQL query 35 | $set = $dbh->prepare("INSERT INTO `log` (`value`, `date`) VALUES (:text, :date)"); 36 | $set->bindParam(':text', $text, \PDO::PARAM_STR); 37 | $set->bindParam(':date', $now, \PDO::PARAM_INT); 38 | return $set->execute(); 39 | } 40 | 41 | switch ($argv[1]) { 42 | case 'updateGames': 43 | updateGames($dbh); 44 | break; 45 | 46 | case 'updateImages': 47 | updateImages($dbh); 48 | break; 49 | 50 | case 'updateGamesImages': 51 | updateGames($dbh); 52 | updateImages($dbh); 53 | break; 54 | 55 | case 'clearTags': 56 | clearTags($dbh); 57 | break; 58 | 59 | default: 60 | echo "Invalid Task"; 61 | break; 62 | } 63 | 64 | function updateGames($dbh){ 65 | addLog('Start task "updateGames"'); 66 | // Prepare SQL query 67 | $add = $dbh->prepare(" 68 | INSERT IGNORE INTO `games` 69 | (`id`, `title`, `indev`, `slug`, `thumb_id`, `bg_id`, `slug_folder`, `url`, `release_date`, `developer`, `publisher`, `category`, `hidden`) 70 | VALUES (:id, :title, :indev, :slug, :thumb_id, :bg_id, :slug, :url, :rlsdate, :dev, :pub, :cat, 1); 71 | "); 72 | $add->bindParam(':id', $id, \PDO::PARAM_INT); 73 | $add->bindParam(':title', $title, \PDO::PARAM_STR); 74 | $add->bindParam(':indev', $inDev, \PDO::PARAM_INT); 75 | $add->bindParam(':slug', $slug, \PDO::PARAM_STR); 76 | $add->bindParam(':thumb_id', $thumb, \PDO::PARAM_STR); 77 | $add->bindParam(':bg_id', $bg, \PDO::PARAM_STR); 78 | $add->bindParam(':url', $url, \PDO::PARAM_STR); 79 | $add->bindParam(':rlsdate', $releaseDate, \PDO::PARAM_INT); 80 | $add->bindParam(':dev', $developer, \PDO::PARAM_STR); 81 | $add->bindParam(':pub', $publisher, \PDO::PARAM_STR); 82 | $add->bindParam(':cat', $category, \PDO::PARAM_STR); 83 | 84 | $client = new GuzzleHttp\Client(); 85 | $cookieJar = GuzzleHttp\Cookie\CookieJar::fromArray([ 86 | 'gog_lc' => 'US_USD_en-US' 87 | ], '.gog.com'); 88 | $page = 1; 89 | while (true) { 90 | $res = $client->request('GET', "https://www.gog.com/games/ajax/filtered?mediaType=game&page=$page&limit=48", ['cookies' => $cookieJar]); 91 | $status = $res->getStatusCode(); 92 | if ($status === 200) { 93 | $json = json_decode($res->getBody(), true); 94 | $products = $json['products']; 95 | $totalPages = intval($json['totalPages']); 96 | $page = intval($json['page']); 97 | if ($page <= $totalPages) { 98 | foreach ($products as $key => $product) { 99 | $id = $product['id']; 100 | $title = $product['title']; 101 | $slug = $product['slug']; 102 | $category = $product['category']; 103 | $url = $product['url']; 104 | if ($url != '') { 105 | $url = 'https://www.gog.com'.$url; 106 | } 107 | $releaseDate = $product['releaseDate']; 108 | $inDev = $product['isInDevelopment']; 109 | $developer = $product['developer']; 110 | $publisher = $product['publisher']; 111 | $add->execute(); 112 | if ($add->rowCount() > 0) { 113 | addLog("Added $title"); 114 | } 115 | } 116 | $page++; 117 | } else { 118 | break; 119 | } 120 | } else { 121 | break; 122 | } 123 | } 124 | addLog('Done task "updateGames"'); 125 | } 126 | 127 | function updateImages($dbh){ 128 | global $CONFIG; 129 | addLog('Start task "updateImages"'); 130 | // List games to work on 131 | $empty = $dbh->prepare('SELECT `title`, `id`, `bg_id`, `thumb_id` FROM `games` WHERE `bg_id` IS NULL OR `thumb_id` IS NULL'); 132 | $empty->execute(); 133 | $emptyImages = $empty->fetchAll(\PDO::FETCH_ASSOC); 134 | 135 | // Prepare SQL query 136 | $updateBG = $dbh->prepare("UPDATE `games` SET `bg_id` = :bg_id WHERE `id` = :id"); 137 | $updateBG->bindParam(':id', $id, \PDO::PARAM_INT); 138 | $updateBG->bindParam(':bg_id', $bg_id, \PDO::PARAM_STR); 139 | 140 | $updateThumb = $dbh->prepare("UPDATE `games` SET `thumb_id` = :thumb_id WHERE `id` = :id"); 141 | $updateThumb->bindParam(':id', $id, \PDO::PARAM_INT); 142 | $updateThumb->bindParam(':thumb_id', $thumb_id, \PDO::PARAM_STR); 143 | 144 | $client = new GuzzleHttp\Client(); 145 | 146 | $bgcount = 0; 147 | $thumbcount = 0; 148 | $affectedGames = []; 149 | $fail = []; 150 | 151 | // Work on images 152 | foreach ($emptyImages as $key => $game) { 153 | $id = $game['id']; 154 | $title = $game['title']; 155 | $affectedGames[$id] = [ 156 | 'title' => $title, 157 | 'thumb' => false, 158 | 'bg' => false 159 | ]; 160 | $rand = md5(openssl_random_pseudo_bytes(5)); 161 | try { 162 | $res = $client->request('GET', "https://api.gog.com/products/$id?$rand"); 163 | } catch (\GuzzleHttp\Exception\ClientException $e) { 164 | $fail[] = $id; 165 | continue; 166 | } 167 | 168 | $json = json_decode($res->getBody(), true); 169 | 170 | if ($game['bg_id'] === null) { 171 | // Try downloading backgrounds 172 | $bg = $json['images']['background']; 173 | preg_match('/gog-statics\.com\/([a-z0-9]{64})\.jpg/', $bg, $bgmatch); 174 | $bg_id = $bgmatch[1]; 175 | $updateBG->execute(); 176 | addLog("Added background for $title"); 177 | } 178 | 179 | if ($game['thumb_id'] === null) { 180 | // Try thumbnail 181 | $thumb = $json['images']['logo']; 182 | preg_match('/gog-statics\.com\/([a-z0-9]{64})_glx_logo\.jpg/', $thumb, $thumbmatch); 183 | $thumb_id = $thumbmatch[1]; 184 | $updateThumb->execute(); 185 | addLog("Added thumbnail for $title"); 186 | } 187 | } 188 | addLog('Done task "updateImages"'); 189 | } 190 | 191 | function clearTags($dbh){ 192 | global $CONFIG; 193 | $Elastic = new Elastic(); 194 | $getIds = $dbh->prepare(' 195 | SELECT `id` fROM `games` 196 | WHERE (`new` = 1 OR `updated` = 1) AND `last_update` <= (UNIX_TIMESTAMP() - 1209600) 197 | AND `hidden` != 1 198 | '); 199 | $getIds->execute(); 200 | $ids = $getIds->fetchAll(PDO::FETCH_COLUMN, 0); 201 | 202 | $clear = $dbh->prepare(' 203 | UPDATE `games` SET `updated` = 0, `new` = 0 204 | WHERE (`new` = 1 OR `updated` = 1) AND `last_update` <= (UNIX_TIMESTAMP() - 1209600) 205 | AND `hidden` != 1 206 | '); 207 | $clear->execute(); 208 | 209 | foreach ($ids as $key => $id) { 210 | $Elastic->UpdateGame($id); 211 | } 212 | 213 | $count = $clear->rowCount(); 214 | if ($count > 0) { 215 | addLog("Cleared tags of $count games."); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /templates/imports/details.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% verbatim %} 19 | 150 | 151 |
152 |
153 |
154 | {% endverbatim %} -------------------------------------------------------------------------------- /web/static/js/admin.js: -------------------------------------------------------------------------------- 1 | document.getElementById('updateGames').addEventListener('click', function(evt) { 2 | http.get({ 3 | url: '/api/v1/updateGamesImages', 4 | headers: { 5 | 'X-Api-Key': APIKEY 6 | } 7 | }, function(res){ 8 | window.alert('GOG Game Grab™ Started!'); 9 | }); 10 | }); 11 | 12 | document.getElementById('updateImages').addEventListener('click', function(evt) { 13 | evt.preventDefault(); 14 | http.get({ 15 | url: '/api/v1/updateImages', 16 | headers: { 17 | 'X-Api-Key': APIKEY 18 | } 19 | }, function(res){ 20 | window.alert('Images Grab™ Started!'); 21 | }); 22 | }); 23 | 24 | document.getElementById('addGameViaId').addEventListener('submit', function(evt) { 25 | evt.preventDefault(); 26 | var form = new FormData(this); 27 | http.post({ 28 | url: '/api/v1/addgamebasedonid', 29 | data: form, 30 | headers: { 31 | 'X-Api-Key': APIKEY 32 | } 33 | }, function(res){ 34 | var json = JSON.parse(res); 35 | if (json.SUCCESS) { 36 | window.alert(json.MSG); 37 | } else { 38 | window.alert('Something fucked up!'); 39 | } 40 | }); 41 | }); 42 | 43 | document.getElementById('batch-file').addEventListener('change', function(evt) { 44 | var files = evt.target.files; 45 | var file = files[0]; 46 | if (file) { 47 | var reader = new FileReader(); 48 | reader.readAsText(file, "UTF-8"); 49 | reader.onload = function (evt) { 50 | document.getElementById('batch-textarea').value = evt.target.result; 51 | }; 52 | reader.onerror = function (evt) { 53 | document.getElementById('batch-textarea').value = "Error reading file."; 54 | }; 55 | } 56 | }); 57 | 58 | document.getElementById('batch-edit').addEventListener('submit', function(evt) { 59 | evt.preventDefault(); 60 | var form = new FormData(this); 61 | http.post({ 62 | url: '/api/v1/games/batchedit', 63 | data: form, 64 | headers: { 65 | 'X-Api-Key': APIKEY 66 | } 67 | }, function(res){ 68 | var json = JSON.parse(res); 69 | window.alert(json.MSG); 70 | }); 71 | }); 72 | 73 | 74 | function refreshLogs(){ 75 | // Get Logs 76 | http.get({ 77 | url: '/api/v1/getlog', 78 | headers: { 79 | 'X-Api-Key': APIKEY 80 | } 81 | }, function(res){ 82 | var json = JSON.parse(res); 83 | var str = ''; 84 | for (var i = 0; i < json.length; i++) { 85 | var id = json[i].id; 86 | var value = json[i].value; 87 | var date = json[i].date; 88 | date = moment(date*1000).format('MMM Do YYYY, h:mm:ss A'); 89 | str = str+''; 90 | } 91 | document.getElementById('log').innerHTML = str; 92 | }); 93 | } 94 | 95 | setInterval(refreshLogs, 15000); 96 | refreshLogs(); 97 | 98 | var limit = 15; 99 | var showHidden = false; 100 | var searchTerm = null; 101 | var params = {}; 102 | var currentGet = null; 103 | var sourceData = null; 104 | var changedRows = {}; 105 | function getGames(){ 106 | if (currentGet !== null) { 107 | currentGet.abort(); 108 | } 109 | currentGet = http.get({ 110 | url: '/api/v1/getgames', 111 | data: Object.assign({limit: limit, showHidden: showHidden, term: searchTerm}, params), 112 | headers: { 113 | 'X-Api-Key': APIKEY 114 | } 115 | }, function(res){ 116 | var data = JSON.parse(res); 117 | gameEdit.loadData(data.data); 118 | gameEdit.loadData(data.data); 119 | // Have to add twice cause Handsontable bug 120 | 121 | sourceData = JSON.parse(JSON.stringify(data.data)); 122 | gameEditEl.classList.add('overflow'); 123 | gameEdit.updateSettings({ 124 | colHeaders: data.headers, 125 | width: gameEditEl.clientWidth 126 | }); 127 | }); 128 | } 129 | 130 | function saveGames(){ 131 | http.post({ 132 | url: '/api/v1/savegames', 133 | data: { 134 | data: JSON.stringify(changedRows) 135 | }, 136 | headers: { 137 | 'X-Api-Key': APIKEY 138 | } 139 | }, function(res){ 140 | var data = JSON.parse(res); 141 | console.log(data); 142 | changedRows = {}; 143 | document.querySelector('[data-changes-amount]').innerHTML = '0'; 144 | }); 145 | } 146 | 147 | Handsontable.renderers.registerRenderer('god.moment.unix', function(hotInstance, td, row, column, prop, value, cellProperties){ 148 | if (parseInt(value) > 0) { 149 | td.innerHTML = moment.unix(value).format('llll'); 150 | } else { 151 | td.innerHTML = 'null'; 152 | } 153 | return td; 154 | }); 155 | 156 | Handsontable.renderers.registerRenderer('god.bool', function(hotInstance, td, row, column, prop, value, cellProperties){ 157 | if (value == '0') { 158 | td.innerHTML = 'false'; 159 | } else if (value == '1'){ 160 | td.innerHTML = 'true'; 161 | } 162 | return td; 163 | }); 164 | 165 | document.getElementById('saveRows').addEventListener('click', saveGames); 166 | 167 | var colBool = { type: 'dropdown', source: ['true', 'false'], sortIndicator: true }; 168 | var colDateTime = { 169 | type: 'date', 170 | renderer: 'god.moment.unix', 171 | sortIndicator: true, 172 | correctFormat: true, 173 | dateFormat: 'X', 174 | datePickerConfig: { 175 | yearRange: [1950, moment().year()+1], 176 | showSeconds: false, 177 | use24hour: false 178 | } 179 | }; 180 | 181 | var gameEditEl = document.getElementById('game-edit-table'); 182 | var gameEdit = new Handsontable(gameEditEl, { 183 | rowHeaders: false, 184 | afterInit: getGames, 185 | columnSorting: true, 186 | manualColumnResize: true, 187 | afterColumnSort: function(colIndex, sorted){ 188 | if (typeof(gameEdit.getSettings().columns[colIndex].sortIndicator) === 'boolean'){ 189 | var colName = gameEdit.getColHeader(colIndex); 190 | if (typeof(sorted) === 'undefined') { 191 | params = {}; 192 | getGames(); 193 | return; 194 | } 195 | params = {sort: colName, sortOrder: sorted}; 196 | getGames(); 197 | } 198 | // Can't figure out how to stop a Handsontable event properly 199 | throw "not actually an exception"; 200 | }, 201 | afterChange: function (change, source) { 202 | if (source === 'loadData') { 203 | return; 204 | } 205 | if (source === 'edit' || source === 'Autofill.fill') { 206 | for (var i = change.length - 1; i >= 0; i--) { 207 | // check if actually changed 208 | var c = change[i]; 209 | var gameID = parseInt(gameEdit.getSourceDataAtRow(c[0])[0]); 210 | var columnName = gameEdit.getColHeader(c[1]); 211 | var sourceRow = sourceData[c[0]]; 212 | var sourceVal = sourceRow[c[1]]; 213 | var newRow = gameEdit.getSourceDataAtRow(c[0]); 214 | var newVal = c[3]; 215 | if (JSON.stringify(sourceRow) !== JSON.stringify(newRow)) { 216 | changedRows[columnName+'_'+gameID] = { 217 | id: gameID, 218 | old: sourceVal, 219 | new: newVal, 220 | column: gameEdit.getColHeader(c[1]) 221 | }; 222 | } else { 223 | if (changedRows[columnName+'_'+gameID] !== undefined) { 224 | delete changedRows[columnName+'_'+gameID]; 225 | } 226 | } 227 | } 228 | } 229 | document.querySelector('[data-changes-amount]').innerHTML = Object.keys(changedRows).length; 230 | }, 231 | columns: [ 232 | { 233 | readOnly: true, 234 | sortIndicator: true 235 | }, 236 | { 237 | sortIndicator: true 238 | }, 239 | colBool, 240 | colBool, 241 | colBool, 242 | colBool, 243 | colBool, 244 | colBool, 245 | colDateTime, 246 | colDateTime, 247 | { 248 | sortIndicator: true 249 | }, 250 | { 251 | sortIndicator: true 252 | }, 253 | { 254 | sortIndicator: true 255 | }, 256 | colDateTime, 257 | { 258 | sortIndicator: true 259 | }, 260 | { 261 | sortIndicator: true 262 | }, 263 | { 264 | sortIndicator: true 265 | }, 266 | { 267 | sortIndicator: true 268 | }, 269 | { 270 | sortIndicator: true 271 | } 272 | ] 273 | }); 274 | 275 | var gameEditOptEl = document.getElementById('game-edit-options'); 276 | 277 | var updateSettings = debounce(function(evt) { 278 | evt.preventDefault(); 279 | var form = new FormData(this); 280 | 281 | // set global variables 282 | limit = form.get('limit'); 283 | 284 | if (form.get('showHidden') == 'on') { 285 | showHidden = true; 286 | } else { 287 | showHidden = false; 288 | } 289 | 290 | searchTerm = form.get('search'); 291 | 292 | getGames(); 293 | }, 200); 294 | 295 | gameEditOptEl.addEventListener('change', updateSettings); 296 | gameEditOptEl.addEventListener('keyup', updateSettings); -------------------------------------------------------------------------------- /web/static/css/_mq.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; // Fixes an issue where Ruby locale is not set properly 2 | // See https://github.com/sass-mq/sass-mq/pull/10 3 | 4 | /// Base font size on the `` element 5 | /// @type Number (unit) 6 | $mq-base-font-size: 16px !default; 7 | 8 | /// Responsive mode 9 | /// 10 | /// Set to `false` to enable support for browsers that do not support @media queries, 11 | /// (IE <= 8, Firefox <= 3, Opera <= 9) 12 | /// 13 | /// You could create a stylesheet served exclusively to older browsers, 14 | /// where @media queries are rasterized 15 | /// 16 | /// @example scss 17 | /// // old-ie.scss 18 | /// $mq-responsive: false; 19 | /// @import 'main'; // @media queries in this file will be rasterized up to $mq-static-breakpoint 20 | /// // larger breakpoints will be ignored 21 | /// 22 | /// @type Boolean 23 | /// @link https://github.com/sass-mq/sass-mq#responsive-mode-off Disabled responsive mode documentation 24 | $mq-responsive: true !default; 25 | 26 | /// Breakpoint list 27 | /// 28 | /// Name your breakpoints in a way that creates a ubiquitous language 29 | /// across team members. It will improve communication between 30 | /// stakeholders, designers, developers, and testers. 31 | /// 32 | /// @type Map 33 | /// @link https://github.com/sass-mq/sass-mq#seeing-the-currently-active-breakpoint Full documentation and examples 34 | $mq-breakpoints: ( 35 | mobile: 320px, 36 | tablet: 740px, 37 | desktop: 980px, 38 | wide: 1300px 39 | ) !default; 40 | 41 | /// Static breakpoint (for fixed-width layouts) 42 | /// 43 | /// Define the breakpoint from $mq-breakpoints that should 44 | /// be used as the target width for the fixed-width layout 45 | /// (i.e. when $mq-responsive is set to 'false') in a old-ie.scss 46 | /// 47 | /// @example scss 48 | /// // tablet-only.scss 49 | /// // 50 | /// // Ignore all styles above tablet breakpoint, 51 | /// // and fix the styles (e.g. layout) at tablet width 52 | /// $mq-responsive: false; 53 | /// $mq-static-breakpoint: tablet; 54 | /// @import 'main'; // @media queries in this file will be rasterized up to tablet 55 | /// // larger breakpoints will be ignored 56 | /// 57 | /// @type String 58 | /// @link https://github.com/sass-mq/sass-mq#adding-custom-breakpoints Full documentation and examples 59 | $mq-static-breakpoint: desktop !default; 60 | 61 | /// Show breakpoints in the top right corner 62 | /// 63 | /// If you want to display the currently active breakpoint in the top 64 | /// right corner of your site during development, add the breakpoints 65 | /// to this list, ordered by width, e.g. (mobile, tablet, desktop). 66 | /// 67 | /// @type map 68 | $mq-show-breakpoints: () !default; 69 | 70 | /// Customize the media type (e.g. `@media screen` or `@media print`) 71 | /// By default sass-mq uses an "all" media type (`@media all and …`) 72 | /// 73 | /// @type String 74 | /// @link https://github.com/sass-mq/sass-mq#changing-media-type Full documentation and examples 75 | $mq-media-type: all !default; 76 | 77 | /// Convert pixels to ems 78 | /// 79 | /// @param {Number} $px - value to convert 80 | /// @param {Number} $base-font-size ($mq-base-font-size) - `` font size 81 | /// 82 | /// @example scss 83 | /// $font-size-in-ems: mq-px2em(16px); 84 | /// p { font-size: mq-px2em(16px); } 85 | /// 86 | /// @requires $mq-base-font-size 87 | /// @returns {Number} 88 | @function mq-px2em($px, $base-font-size: $mq-base-font-size) { 89 | @if unitless($px) { 90 | @warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels."; 91 | @return mq-px2em($px * 1px, $base-font-size); 92 | } @else if unit($px) == em { 93 | @return $px; 94 | } 95 | @return ($px / $base-font-size) * 1em; 96 | } 97 | 98 | /// Get a breakpoint's width 99 | /// 100 | /// @param {String} $name - Name of the breakpoint. One of $mq-breakpoints 101 | /// 102 | /// @example scss 103 | /// $tablet-width: mq-get-breakpoint-width(tablet); 104 | /// @media (min-width: mq-get-breakpoint-width(desktop)) {} 105 | /// 106 | /// @requires {Variable} $mq-breakpoints 107 | /// 108 | /// @returns {Number} Value in pixels 109 | @function mq-get-breakpoint-width($name, $breakpoints: $mq-breakpoints) { 110 | @if map-has-key($breakpoints, $name) { 111 | @return map-get($breakpoints, $name); 112 | } @else { 113 | @warn "Breakpoint #{$name} wasn't found in $breakpoints."; 114 | } 115 | } 116 | 117 | /// Media Query mixin 118 | /// 119 | /// @param {String | Boolean} $from (false) - One of $mq-breakpoints 120 | /// @param {String | Boolean} $until (false) - One of $mq-breakpoints 121 | /// @param {String | Boolean} $and (false) - Additional media query parameters 122 | /// @param {String} $media-type ($mq-media-type) - Media type: screen, print… 123 | /// 124 | /// @ignore Undocumented API, for advanced use only: 125 | /// @ignore @param {Map} $breakpoints ($mq-breakpoints) 126 | /// @ignore @param {String} $static-breakpoint ($mq-static-breakpoint) 127 | /// 128 | /// @content styling rules, wrapped into a @media query when $responsive is true 129 | /// 130 | /// @requires {Variable} $mq-media-type 131 | /// @requires {Variable} $mq-breakpoints 132 | /// @requires {Variable} $mq-static-breakpoint 133 | /// @requires {function} mq-px2em 134 | /// @requires {function} mq-get-breakpoint-width 135 | /// 136 | /// @link https://github.com/sass-mq/sass-mq#responsive-mode-on-default Full documentation and examples 137 | /// 138 | /// @example scss 139 | /// .element { 140 | /// @include mq($from: mobile) { 141 | /// color: red; 142 | /// } 143 | /// @include mq($until: tablet) { 144 | /// color: blue; 145 | /// } 146 | /// @include mq(mobile, tablet) { 147 | /// color: green; 148 | /// } 149 | /// @include mq($from: tablet, $and: '(orientation: landscape)') { 150 | /// color: teal; 151 | /// } 152 | /// @include mq(950px) { 153 | /// color: hotpink; 154 | /// } 155 | /// @include mq(tablet, $media-type: screen) { 156 | /// color: hotpink; 157 | /// } 158 | /// // Advanced use: 159 | /// $my-breakpoints: (L: 900px, XL: 1200px); 160 | /// @include mq(L, $breakpoints: $my-breakpoints, $static-breakpoint: L) { 161 | /// color: hotpink; 162 | /// } 163 | /// } 164 | @mixin mq( 165 | $from: false, 166 | $until: false, 167 | $and: false, 168 | $media-type: $mq-media-type, 169 | $breakpoints: $mq-breakpoints, 170 | $responsive: $mq-responsive, 171 | $static-breakpoint: $mq-static-breakpoint 172 | ) { 173 | $min-width: 0; 174 | $max-width: 0; 175 | $media-query: ''; 176 | 177 | // From: this breakpoint (inclusive) 178 | @if $from { 179 | @if type-of($from) == number { 180 | $min-width: mq-px2em($from); 181 | } @else { 182 | $min-width: mq-px2em(mq-get-breakpoint-width($from, $breakpoints)); 183 | } 184 | } 185 | 186 | // Until: that breakpoint (exclusive) 187 | @if $until { 188 | @if type-of($until) == number { 189 | $max-width: mq-px2em($until); 190 | } @else { 191 | $max-width: mq-px2em(mq-get-breakpoint-width($until, $breakpoints)) - .01em; 192 | } 193 | } 194 | 195 | // Responsive support is disabled, rasterize the output outside @media blocks 196 | // The browser will rely on the cascade itself. 197 | @if $responsive == false { 198 | $static-breakpoint-width: mq-get-breakpoint-width($static-breakpoint, $breakpoints); 199 | $target-width: mq-px2em($static-breakpoint-width); 200 | 201 | // Output only rules that start at or span our target width 202 | @if ( 203 | $and == false 204 | and $min-width <= $target-width 205 | and ( 206 | $until == false or $max-width >= $target-width 207 | ) 208 | ) { 209 | @content; 210 | } 211 | } 212 | 213 | // Responsive support is enabled, output rules inside @media queries 214 | @else { 215 | @if $min-width != 0 { $media-query: '#{$media-query} and (min-width: #{$min-width})'; } 216 | @if $max-width != 0 { $media-query: '#{$media-query} and (max-width: #{$max-width})'; } 217 | @if $and { $media-query: '#{$media-query} and #{$and}'; } 218 | 219 | // Remove unnecessary media query prefix 'all and ' 220 | @if ($media-type == 'all' and $media-query != '') { 221 | $media-type: ''; 222 | $media-query: str-slice(unquote($media-query), 6); 223 | } 224 | 225 | @media #{$media-type + $media-query} { 226 | @content; 227 | } 228 | } 229 | } 230 | 231 | /// Add a breakpoint 232 | /// 233 | /// @param {String} $name - Name of the breakpoint 234 | /// @param {Number} $width - Width of the breakpoint 235 | /// 236 | /// @requires {Variable} $mq-breakpoints 237 | /// 238 | /// @example scss 239 | /// @include mq-add-breakpoint(tvscreen, 1920px); 240 | /// @include mq(tvscreen) {} 241 | @mixin mq-add-breakpoint($name, $width) { 242 | $new-breakpoint: ($name: $width); 243 | $mq-breakpoints: map-merge($mq-breakpoints, $new-breakpoint) !global; 244 | } 245 | 246 | /// Show the active breakpoint in the top right corner of the viewport 247 | /// @link https://github.com/sass-mq/sass-mq#seeing-the-currently-active-breakpoint 248 | /// 249 | /// @param {List} $show-breakpoints ($mq-show-breakpoints) - List of breakpoints to show in the top right corner 250 | /// @param {Map} $breakpoints ($mq-breakpoints) - Breakpoint names and sizes 251 | /// 252 | /// @requires {Variable} $mq-breakpoints 253 | /// @requires {Variable} $mq-show-breakpoints 254 | /// 255 | /// @example scss 256 | /// // Show breakpoints using global settings 257 | /// @include mq-show-breakpoints; 258 | /// 259 | /// // Show breakpoints using custom settings 260 | /// @include mq-show-breakpoints((L, XL), (S: 300px, L: 800px, XL: 1200px)); 261 | @mixin mq-show-breakpoints($show-breakpoints: $mq-show-breakpoints, $breakpoints: $mq-breakpoints) { 262 | body:before { 263 | background-color: #FCF8E3; 264 | border-bottom: 1px solid #FBEED5; 265 | border-left: 1px solid #FBEED5; 266 | color: #C09853; 267 | font: small-caption; 268 | padding: 3px 6px; 269 | pointer-events: none; 270 | position: fixed; 271 | right: 0; 272 | top: 0; 273 | z-index: 100; 274 | 275 | // Loop through the breakpoints that should be shown 276 | @each $show-breakpoint in $show-breakpoints { 277 | $width: mq-get-breakpoint-width($show-breakpoint, $breakpoints); 278 | @include mq($show-breakpoint, $breakpoints: $breakpoints) { 279 | content: "#{$show-breakpoint} ≥ #{$width} (#{mq-px2em($width)})"; 280 | } 281 | } 282 | } 283 | } 284 | 285 | @if length($mq-show-breakpoints) > 0 { 286 | @include mq-show-breakpoints; 287 | } 288 | -------------------------------------------------------------------------------- /templates/game.twig: -------------------------------------------------------------------------------- 1 | {# 2 | GOGGames 3 | Copyright (C) 2018 GoodOldDownloads 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | #} 18 | {% extends 'main.twig' %} 19 | 20 | {% block title %}{{ game.title }}{% endblock title %} 21 | {% set game = game[0] %} 22 | 23 | {% block meta %} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% endblock meta %} 33 | 34 | {% block content %} 35 | {% import "imports/card.twig" as card %} 36 |
37 |
38 |
39 |
40 |

{{ game.title }}

41 | 42 | {% if validcaptcha %} 43 | 44 | {% else %} 45 |
46 | 47 | 48 |
49 | {% endif %} 50 | 51 | 52 | 137 |
138 | {% if game.files.GAME %} 139 |
140 |
{{ 'Game Items Included'|trans }}
141 | {% for file in game.files.GAME %} 142 |
{{ file.size ? file.size|convertBytes : '' }}{{ file.name }}
143 | {% endfor %} 144 |
145 | {% endif %} 146 | {% if game.files.PATCHES %} 147 |
148 |
{{ 'Patch/Other Items Included'|trans }}
149 | {% for file in game.files.PATCHES %} 150 |
{{ file.size ? file.size|convertBytes : '' }}{{ file.name }}
151 | {% endfor %} 152 |
153 | {% endif %} 154 | {% if game.files.GOODIES %} 155 |
156 |
{{ 'Goodies Included'|trans }}
157 | {% for file in game.files.GOODIES %} 158 |
{{ file.size ? file.size|convertBytes : '' }}{{ file.name }}
159 | {% endfor %} 160 |
161 | {% endif %} 162 |
163 |
164 |
165 | {% endblock content %} 166 | 167 | {% block scripts %} 168 | 174 | 175 | {% endblock scripts %} -------------------------------------------------------------------------------- /Elastic.class.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | class Elastic 21 | { 22 | 23 | private $client = null; 24 | 25 | public function __construct($hosts = ['localhost']) 26 | { 27 | $this->client = Elasticsearch\ClientBuilder::create()->setHosts($hosts)->build(); 28 | } 29 | public function Mapping(){ 30 | $params = [ 31 | 'index' => 'gg', 32 | 'body' => [ 33 | 'settings' => [ 34 | 'number_of_shards' => 1, 35 | 'analysis' => [ 36 | 'filter' => [ 37 | 'autocomplete_filter' => [ 38 | 'type' => 'ngram', 39 | 'min_gram' => 3, 40 | 'max_gram' => 15 41 | ] 42 | ], 43 | 'analyzer' => [ 44 | 'autocomplete' => [ 45 | 'type' => 'custom', 46 | 'tokenizer' => 'standard', 47 | 'filter' => [ 48 | 'lowercase', 49 | 'autocomplete_filter' 50 | ] 51 | ], 52 | 'lowerkey' => [ 53 | 'type' => 'custom', 54 | 'tokenizer' => 'keyword', 55 | 'filter' => [ 56 | 'lowercase' 57 | ] 58 | ] 59 | ], 60 | 'normalizer' => [ 61 | 'lowernormalizer' => [ 62 | 'type' => 'custom', 63 | 'filter' => [ 64 | 'lowercase' 65 | ] 66 | ] 67 | ] 68 | ] 69 | ], 70 | 'mappings' => [ 71 | 'gg_game' => [ 72 | 'properties' => [ 73 | 'id' => [ 74 | 'type' => 'integer' 75 | ], 76 | 'title' => [ 77 | 'type' => 'text', 78 | //'analyzer' => 'autocomplete', 79 | 'fields' => [ 80 | 'raw' => [ 81 | 'type' => 'keyword', 82 | 'normalizer' => 'lowernormalizer' 83 | ] 84 | ] 85 | ], 86 | 'indev' => [ 87 | 'type' => 'integer' 88 | ], 89 | 'new' => [ 90 | 'type' => 'integer' 91 | ], 92 | 'updated' => [ 93 | 'type' => 'integer' 94 | ], 95 | 'last_upload' => [ 96 | 'type' => 'date', 97 | 'format' => 'epoch_second' 98 | ], 99 | 'last_update' => [ 100 | 'type' => 'date', 101 | 'format' => 'epoch_second' 102 | ], 103 | 'bg_id' => [ 104 | 'type' => 'text' 105 | ], 106 | 'thumb_id' => [ 107 | 'type' => 'text' 108 | ], 109 | 'slug' => [ 110 | 'type' => 'text' 111 | ], 112 | 'slug_folder' => [ 113 | 'type' => 'text' 114 | ], 115 | 'url' => [ 116 | 'type' => 'text' 117 | ], 118 | 'release_date' => [ 119 | 'type' => 'date', 120 | 'format' => 'epoch_second' 121 | ], 122 | 'developer' => [ 123 | 'type' => 'text', 124 | 'analyzer' => 'lowerkey' 125 | ], 126 | 'publisher' => [ 127 | 'type' => 'text', 128 | 'analyzer' => 'lowerkey' 129 | ], 130 | 'category' => [ 131 | 'type' => 'keyword' 132 | ], 133 | 'hidden' => [ 134 | 'type' => 'integer' 135 | ], 136 | 'uploading' => [ 137 | 'type' => 'integer' 138 | ], 139 | 'queued' => [ 140 | 'type' => 'integer' 141 | ], 142 | 'old_view' => [ 143 | 'type' => 'boolean' 144 | ], 145 | 'votes' => [ 146 | 'type' => 'integer' 147 | ] 148 | ] 149 | ] 150 | ] 151 | ] 152 | ]; 153 | $this->client->indices()->create($params); 154 | } 155 | public function Clear(){ 156 | $this->client->indices()->delete(['index' => 'gg']); 157 | } 158 | public function InsertAll(){ 159 | global $dbh; 160 | $this->Mapping(); 161 | $client = $this->client; 162 | $getGames = $dbh->prepare("SELECT `game_id`, games.*, COUNT(`game_id`) as `votes` 163 | FROM `games` 164 | LEFT JOIN `votes` ON `game_id` = `id` 165 | WHERE `hidden` = 0 166 | GROUP BY `id`"); 167 | $getGames->execute(); 168 | $games = $getGames->fetchAll(\PDO::FETCH_ASSOC); 169 | $games = array_chunk($games, 1000); 170 | 171 | foreach ($games as $key_chunk => $game_chunk) { 172 | $params = []; 173 | foreach ($game_chunk as $key => $game) { 174 | $gameId = $game['id']; 175 | 176 | $params['body'][] = array( 177 | 'index' => array( 178 | '_index' => 'gg', 179 | '_type' => 'gg_game', 180 | '_id' => $gameId 181 | ), 182 | ); 183 | 184 | $params['body'][] = [ 185 | 'title' => $game['title'], 186 | 'indev' => $game['indev'], 187 | 'new' => $game['new'], 188 | 'updated' => $game['updated'], 189 | 'last_upload' => intval($game['last_upload']), 190 | 'last_update' => intval($game['last_update']), 191 | 'bg_id' => $game['bg_id'], 192 | 'thumb_id' => $game['thumb_id'], 193 | 'slug' => $game['slug'], 194 | 'slug_folder' => $game['slug_folder'], 195 | 'url' => $game['url'], 196 | 'release_date' => $game['release_date'], 197 | 'developer' => $game['developer'], 198 | 'publisher' => $game['publisher'], 199 | 'category' => $game['category'], 200 | 'hidden' => $game['hidden'], 201 | 'uploading' => $game['uploading'], 202 | 'queued' => $game['queued'], 203 | 'votes' => $game['votes'] 204 | ]; 205 | } 206 | $responses = $client->bulk($params); 207 | unset($responses); 208 | $params = []; 209 | } 210 | return true; 211 | } 212 | public function UpdateGame($gameId) 213 | { 214 | global $dbh; 215 | try { 216 | if ($gameId == null) { 217 | throw new \Exception("Game ID is null"); 218 | } 219 | 220 | $getGame = $dbh->prepare("SELECT `game_id`, games.*, COUNT(`game_id`) as `votes` 221 | FROM `games` 222 | LEFT JOIN `votes` ON `game_id` = `id` 223 | WHERE `id` = :game_id 224 | GROUP BY `id`"); 225 | $getGame->bindParam(':game_id', $gameId, \PDO::PARAM_INT); 226 | $getGame->execute(); 227 | $game = $getGame->fetch(\PDO::FETCH_ASSOC); 228 | if ($game['hidden'] == 1) { 229 | return $this->client->delete(['index' => 'gg','type' => 'gg_game','id' => $gameId]); 230 | } 231 | $gameId = $game['id']; 232 | 233 | $params = [ 234 | 'index' => 'gg', 235 | 'type' => 'gg_game', 236 | 'id' => $gameId, 237 | 'body' => [ 238 | 'doc' => [ 239 | 'title' => $game['title'], 240 | 'indev' => $game['indev'], 241 | 'new' => $game['new'], 242 | 'updated' => $game['updated'], 243 | 'last_upload' => intval($game['last_upload']), 244 | 'last_update' => intval($game['last_update']), 245 | 'bg_id' => $game['bg_id'], 246 | 'thumb_id' => $game['thumb_id'], 247 | 'slug' => $game['slug'], 248 | 'slug_folder' => $game['slug_folder'], 249 | 'url' => $game['url'], 250 | 'release_date' => $game['release_date'], 251 | 'developer' => $game['developer'], 252 | 'publisher' => $game['publisher'], 253 | 'category' => $game['category'], 254 | 'hidden' => $game['hidden'], 255 | 'uploading' => $game['uploading'], 256 | 'queued' => $game['queued'], 257 | 'votes' => $game['votes'] 258 | ], 259 | 'doc_as_upsert' => true 260 | ] 261 | ]; 262 | $responses = $this->client->update($params); 263 | } catch(\Exception $e){ 264 | return $e->getMessage(); 265 | } 266 | return $responses; 267 | } 268 | public function msearch($params){ 269 | return $this->client->msearch($params); 270 | } 271 | public function search($params){ 272 | return $this->client->search($params); 273 | } 274 | public function count($params){ 275 | return $this->client->count($params); 276 | } 277 | } -------------------------------------------------------------------------------- /web/static/css/_reboot.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix 2 | 3 | // Reboot 4 | // 5 | // Normalization of HTML elements, manually forked from Normalize.css to remove 6 | // styles targeting irrelevant browsers while applying new styles. 7 | // 8 | // Normalize is licensed MIT. https://github.com/necolas/normalize.css 9 | 10 | 11 | // Document 12 | // 13 | // 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`. 14 | // 2. Change the default font family in all browsers. 15 | // 3. Correct the line height in all browsers. 16 | // 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS. 17 | // 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so 18 | // we force a non-overlapping, non-auto-hiding scrollbar to counteract. 19 | // 6. Change the default tap highlight to be completely transparent in iOS. 20 | 21 | *, 22 | *::before, 23 | *::after { 24 | box-sizing: border-box; // 1 25 | } 26 | 27 | html { 28 | font-family: sans-serif; // 2 29 | line-height: 1.15; // 3 30 | -webkit-text-size-adjust: 100%; // 4 31 | -ms-text-size-adjust: 100%; // 4 32 | -ms-overflow-style: scrollbar; // 5 33 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); // 6 34 | } 35 | 36 | // IE10+ doesn't honor `` in some cases. 37 | @at-root { 38 | @-ms-viewport { 39 | width: device-width; 40 | } 41 | } 42 | 43 | // stylelint-disable selector-list-comma-newline-after 44 | // Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers) 45 | article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section { 46 | display: block; 47 | } 48 | // stylelint-enable selector-list-comma-newline-after 49 | 50 | // Body 51 | // 52 | // 1. Remove the margin in all browsers. 53 | // 2. As a best practice, apply a default `background-color`. 54 | // 3. Set an explicit initial text-align value so that we can later use the 55 | // the `inherit` value on things like `` elements. 56 | 57 | body { 58 | margin: 0; // 1 59 | font-family: $font-family-base; 60 | font-size: $font-size-base; 61 | font-weight: $font-weight-base; 62 | line-height: $line-height-base; 63 | color: $body-color; 64 | text-align: left; // 3 65 | background-color: $body-bg; // 2 66 | } 67 | 68 | // Suppress the focus outline on elements that cannot be accessed via keyboard. 69 | // This prevents an unwanted focus outline from appearing around elements that 70 | // might still respond to pointer events. 71 | // 72 | // Credit: https://github.com/suitcss/base 73 | [tabindex="-1"]:focus { 74 | outline: 0 !important; 75 | } 76 | 77 | 78 | // Content grouping 79 | // 80 | // 1. Add the correct box sizing in Firefox. 81 | // 2. Show the overflow in Edge and IE. 82 | 83 | hr { 84 | box-sizing: content-box; // 1 85 | height: 0; // 1 86 | overflow: visible; // 2 87 | } 88 | 89 | 90 | // 91 | // Typography 92 | // 93 | 94 | // Remove top margins from headings 95 | // 96 | // By default, `

`-`

` all receive top and bottom margins. We nuke the top 97 | // margin for easier control within type scales as it avoids margin collapsing. 98 | // stylelint-disable selector-list-comma-newline-after 99 | h1, h2, h3, h4, h5, h6 { 100 | margin-top: 0; 101 | margin-bottom: $headings-margin-bottom; 102 | } 103 | // stylelint-enable selector-list-comma-newline-after 104 | 105 | // Reset margins on paragraphs 106 | // 107 | // Similarly, the top margin on `

`s get reset. However, we also reset the 108 | // bottom margin to use `rem` units instead of `em`. 109 | p { 110 | margin-top: 0; 111 | margin-bottom: $paragraph-margin-bottom; 112 | } 113 | 114 | // Abbreviations 115 | // 116 | // 1. Remove the bottom border in Firefox 39-. 117 | // 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 118 | // 3. Add explicit cursor to indicate changed behavior. 119 | // 4. Duplicate behavior to the data-* attribute for our tooltip plugin 120 | 121 | abbr[title], 122 | abbr[data-original-title] { // 4 123 | text-decoration: underline; // 2 124 | text-decoration: underline dotted; // 2 125 | cursor: help; // 3 126 | border-bottom: 0; // 1 127 | } 128 | 129 | address { 130 | margin-bottom: 1rem; 131 | font-style: normal; 132 | line-height: inherit; 133 | } 134 | 135 | ol, 136 | ul, 137 | dl { 138 | margin-top: 0; 139 | margin-bottom: 1rem; 140 | } 141 | 142 | ol ol, 143 | ul ul, 144 | ol ul, 145 | ul ol { 146 | margin-bottom: 0; 147 | } 148 | 149 | dt { 150 | font-weight: 600; 151 | } 152 | 153 | dd { 154 | margin-bottom: .5rem; 155 | margin-left: 0; // Undo browser default 156 | } 157 | 158 | blockquote { 159 | margin: 0 0 1rem; 160 | } 161 | 162 | dfn { 163 | font-style: italic; // Add the correct font style in Android 4.3- 164 | } 165 | 166 | // stylelint-disable font-weight-notation 167 | b, 168 | strong { 169 | font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari 170 | } 171 | // stylelint-enable font-weight-notation 172 | 173 | small { 174 | font-size: 80%; // Add the correct font size in all browsers 175 | } 176 | 177 | // 178 | // Prevent `sub` and `sup` elements from affecting the line height in 179 | // all browsers. 180 | // 181 | 182 | sub, 183 | sup { 184 | position: relative; 185 | font-size: 75%; 186 | line-height: 0; 187 | vertical-align: baseline; 188 | } 189 | 190 | sub { bottom: -.25em; } 191 | sup { top: -.5em; } 192 | 193 | 194 | // 195 | // Links 196 | // 197 | 198 | a { 199 | color: $link-color; 200 | text-decoration: $link-decoration; 201 | background-color: transparent; // Remove the gray background on active links in IE 10. 202 | -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+. 203 | &:hover { 204 | color: $link-hover-color; 205 | text-decoration: $link-hover-decoration; 206 | } 207 | } 208 | 209 | // And undo these styles for placeholder links/named anchors (without href) 210 | // which have not been made explicitly keyboard-focusable (without tabindex). 211 | // It would be more straightforward to just use a[href] in previous block, but that 212 | // causes specificity issues in many other styles that are too complex to fix. 213 | // See https://github.com/twbs/bootstrap/issues/19402 214 | 215 | a:not([href]):not([tabindex]) { 216 | color: inherit; 217 | text-decoration: none; 218 | 219 | &:focus, 220 | &:hover { 221 | color: inherit; 222 | text-decoration: none; 223 | } 224 | 225 | &:focus { 226 | outline: 0; 227 | } 228 | } 229 | 230 | 231 | // 232 | // Code 233 | // 234 | 235 | // stylelint-disable font-family-no-duplicate-names 236 | pre, 237 | code, 238 | kbd, 239 | samp { 240 | font-family: monospace, monospace; // Correct the inheritance and scaling of font size in all browsers. 241 | font-size: 1em; // Correct the odd `em` font sizing in all browsers. 242 | } 243 | // stylelint-enable font-family-no-duplicate-names 244 | 245 | pre { 246 | // Remove browser default top margin 247 | margin-top: 0; 248 | // Reset browser default of `1em` to use `rem`s 249 | margin-bottom: 1rem; 250 | // Don't allow content to break outside 251 | overflow: auto; 252 | // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so 253 | // we force a non-overlapping, non-auto-hiding scrollbar to counteract. 254 | -ms-overflow-style: scrollbar; 255 | } 256 | 257 | 258 | // 259 | // Figures 260 | // 261 | 262 | figure { 263 | // Apply a consistent margin strategy (matches our type styles). 264 | margin: 0 0 1rem; 265 | } 266 | 267 | 268 | // 269 | // Images and content 270 | // 271 | 272 | img { 273 | vertical-align: middle; 274 | border-style: none; // Remove the border on images inside links in IE 10-. 275 | } 276 | 277 | svg:not(:root) { 278 | overflow: hidden; // Hide the overflow in IE 279 | } 280 | 281 | 282 | // Avoid 300ms click delay on touch devices that support the `touch-action` CSS property. 283 | // 284 | // In particular, unlike most other browsers, IE11+Edge on Windows 10 on touch devices and IE Mobile 10-11 285 | // DON'T remove the click delay when `` is present. 286 | // However, they DO support removing the click delay via `touch-action: manipulation`. 287 | // See: 288 | // * https://getbootstrap.com/docs/4.0/content/reboot/#click-delay-optimization-for-touch 289 | // * https://caniuse.com/#feat=css-touch-action 290 | // * https://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay 291 | 292 | a, 293 | area, 294 | button, 295 | [role="button"], 296 | input:not([type="range"]), 297 | label, 298 | select, 299 | summary, 300 | textarea { 301 | touch-action: manipulation; 302 | } 303 | 304 | 305 | // 306 | // Tables 307 | // 308 | 309 | table { 310 | border-collapse: collapse; // Prevent double borders 311 | } 312 | 313 | caption { 314 | padding-top: $table-cell-padding; 315 | padding-bottom: $table-cell-padding; 316 | color: $text-muted; 317 | text-align: left; 318 | caption-side: bottom; 319 | } 320 | 321 | th { 322 | // Matches default `` alignment by inheriting from the ``, or the 323 | // closest parent with a set `text-align`. 324 | text-align: inherit; 325 | } 326 | 327 | 328 | // 329 | // Forms 330 | // 331 | 332 | label { 333 | // Allow labels to use `margin` for spacing. 334 | display: inline-block; 335 | margin-bottom: .5rem; 336 | } 337 | 338 | // Remove the default `border-radius` that macOS Chrome adds. 339 | // 340 | // Details at https://github.com/twbs/bootstrap/issues/24093 341 | button { 342 | border-radius: 0; 343 | } 344 | 345 | // Work around a Firefox/IE bug where the transparent `button` background 346 | // results in a loss of the default `button` focus styles. 347 | // 348 | // Credit: https://github.com/suitcss/base/ 349 | button:focus { 350 | outline: 1px dotted; 351 | outline: 5px auto -webkit-focus-ring-color; 352 | } 353 | 354 | input, 355 | button, 356 | select, 357 | optgroup, 358 | textarea { 359 | margin: 0; // Remove the margin in Firefox and Safari 360 | font-family: inherit; 361 | font-size: inherit; 362 | line-height: inherit; 363 | } 364 | 365 | button, 366 | input { 367 | overflow: visible; // Show the overflow in Edge 368 | } 369 | 370 | button, 371 | select { 372 | text-transform: none; // Remove the inheritance of text transform in Firefox 373 | } 374 | 375 | // 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 376 | // controls in Android 4. 377 | // 2. Correct the inability to style clickable types in iOS and Safari. 378 | button, 379 | html [type="button"], // 1 380 | [type="reset"], 381 | [type="submit"] { 382 | -webkit-appearance: button; // 2 383 | } 384 | 385 | // Remove inner border and padding from Firefox, but don't restore the outline like Normalize. 386 | button::-moz-focus-inner, 387 | [type="button"]::-moz-focus-inner, 388 | [type="reset"]::-moz-focus-inner, 389 | [type="submit"]::-moz-focus-inner { 390 | padding: 0; 391 | border-style: none; 392 | } 393 | 394 | input[type="radio"], 395 | input[type="checkbox"] { 396 | box-sizing: border-box; // 1. Add the correct box sizing in IE 10- 397 | padding: 0; // 2. Remove the padding in IE 10- 398 | } 399 | 400 | 401 | input[type="date"], 402 | input[type="time"], 403 | input[type="datetime-local"], 404 | input[type="month"] { 405 | // Remove the default appearance of temporal inputs to avoid a Mobile Safari 406 | // bug where setting a custom line-height prevents text from being vertically 407 | // centered within the input. 408 | // See https://bugs.webkit.org/show_bug.cgi?id=139848 409 | // and https://github.com/twbs/bootstrap/issues/11266 410 | -webkit-appearance: listbox; 411 | } 412 | 413 | textarea { 414 | overflow: auto; // Remove the default vertical scrollbar in IE. 415 | // Textareas should really only resize vertically so they don't break their (horizontal) containers. 416 | resize: vertical; 417 | } 418 | 419 | fieldset { 420 | // Browsers set a default `min-width: min-content;` on fieldsets, 421 | // unlike e.g. `

`s, which have `min-width: 0;` by default. 422 | // So we reset that to ensure fieldsets behave more like a standard block element. 423 | // See https://github.com/twbs/bootstrap/issues/12359 424 | // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements 425 | min-width: 0; 426 | // Reset the default outline behavior of fieldsets so they don't affect page layout. 427 | padding: 0; 428 | margin: 0; 429 | border: 0; 430 | } 431 | 432 | // 1. Correct the text wrapping in Edge and IE. 433 | // 2. Correct the color inheritance from `fieldset` elements in IE. 434 | legend { 435 | display: block; 436 | width: 100%; 437 | max-width: 100%; // 1 438 | padding: 0; 439 | margin-bottom: .5rem; 440 | font-size: 1.5rem; 441 | line-height: inherit; 442 | color: inherit; // 2 443 | white-space: normal; // 1 444 | } 445 | 446 | progress { 447 | vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera. 448 | } 449 | 450 | // Correct the cursor style of increment and decrement buttons in Chrome. 451 | [type="number"]::-webkit-inner-spin-button, 452 | [type="number"]::-webkit-outer-spin-button { 453 | height: auto; 454 | } 455 | 456 | [type="search"] { 457 | // This overrides the extra rounded corners on search inputs in iOS so that our 458 | // `.form-control` class can properly style them. Note that this cannot simply 459 | // be added to `.form-control` as it's not specific enough. For details, see 460 | // https://github.com/twbs/bootstrap/issues/11586. 461 | outline-offset: -2px; // 2. Correct the outline style in Safari. 462 | -webkit-appearance: none; 463 | } 464 | 465 | // 466 | // Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 467 | // 468 | 469 | [type="search"]::-webkit-search-cancel-button, 470 | [type="search"]::-webkit-search-decoration { 471 | -webkit-appearance: none; 472 | } 473 | 474 | // 475 | // 1. Correct the inability to style clickable types in iOS and Safari. 476 | // 2. Change font properties to `inherit` in Safari. 477 | // 478 | 479 | ::-webkit-file-upload-button { 480 | font: inherit; // 2 481 | -webkit-appearance: button; // 1 482 | } 483 | 484 | // 485 | // Correct element displays 486 | // 487 | 488 | output { 489 | display: inline-block; 490 | } 491 | 492 | summary { 493 | display: list-item; // Add the correct display in all browsers 494 | cursor: pointer; 495 | } 496 | 497 | template { 498 | display: none; // Add the correct display in IE 499 | } 500 | 501 | // Always hide an element with the `hidden` HTML attribute (from PureCSS). 502 | // Needed for proper display in IE 10-. 503 | [hidden] { 504 | display: none !important; 505 | } 506 | --------------------------------------------------------------------------------