geoblock
Version:
A minimal geoblocking library for game websites
3 lines (2 loc) • 8.51 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).GeoBlock=e()}(this,(function(){"use strict";return class{constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.presets={sanctions:["CU","IR","KP","SY","VE","CR","UA","RU","BY","KR"],gambling:["US","CN","SG","AE","SA","QA","BN","IR","KP","JP","KR","TH","ID","MY","VN","IN","PK","AF","TR","EG","KH","RU","UA","CY","PL","GR","NO","FI","IS","AU","BR","AR","CO","PE","CL","MA","DZ","TN","LB","IL","JO","KW","BH","OM","YE","BD","PH","NZ","FR","DE","IT","ES","PT","NL","CH","AT","CA"],lottery:["US","CN","JP","KR","SG","ID","MY","TH","AE","SA","QA","BN","IR","YE","PK","AF","DZ","LY","KP","KH","VN","RU","UA","TR","EG","MA","IN","BR","AR","VE","PL","HU","IT","NO","IS"],skillprize:["BR","AE","SA","IT","IN","MX","QA","SE","PL","KY"],raffle:["US","CN","JP","SG","AE","SA","KR","TH","ID","MY"]},this.presetDescriptions={sanctions:t.presetDescriptions?.sanctions||"Countries under international sanctions",gambling:t.presetDescriptions?.gambling||"Countries with strict gambling regulations",lottery:t.presetDescriptions?.lottery||"Countries with strict lottery regulations",skillprize:t.presetDescriptions?.skillprize||"Countries with strict skill-based prize regulations",raffle:t.presetDescriptions?.raffle||"Countries with raffle restrictions",...t.presetDescriptions||{}},t.presets&&"object"==typeof t.presets&&Object.keys(t.presets).forEach((e=>{Array.isArray(t.presets[e])&&(this.presets[e]=[...t.presets[e]])})),this.config={activePresets:t.activePresets||[],additionalCountries:t.additionalCountries||[],exemptCountries:t.exemptCountries||[],blockMessage:t.blockMessage||"We're sorry, access to this site is restricted in your region.",legalEntity:t.legalEntity||"",visualBlocking:void 0===t.visualBlocking||t.visualBlocking,blockingClass:t.blockingClass||"geo-blocked",overlayClass:t.overlayClass||"geo-overlay",messageClass:t.messageClass||"geo-message",dismissOnOverlayClick:void 0===t.dismissOnOverlayClick||t.dismissOnOverlayClick,allowDismiss:void 0===t.allowDismiss||t.allowDismiss,customStyles:t.customStyles||{},testMode:t.testMode||!1,testCountry:t.testCountry||null},this.blockedCountries=this.compileBlockList(),this._lastCountryLookup=null}compileBlockList(){const t=new Set;return this.config.activePresets.forEach((e=>{this.presets[e]&&this.presets[e].forEach((e=>t.add(e)))})),this.config.additionalCountries.forEach((e=>t.add(e))),this.config.exemptCountries.forEach((e=>t.delete(e))),[...t]}async getCountryInfo(){if(this._lastCountryLookup)return this._lastCountryLookup;if(this.config.testMode&&this.config.testCountry){const t={countryCode:this.config.testCountry,country:"Test Country",ip:"0.0.0.0"};return this._lastCountryLookup=t,t}try{const t=await fetch("https://ipapi.co/json/"),e=await t.json();if(e.error)throw new Error(e.reason||"API error");const s={countryCode:e.country_code,country:e.country_name,ip:e.ip};return this._lastCountryLookup=s,s}catch(t){console.error("GeoBlock: Error fetching country data:",t);try{const t=await fetch("https://api.ipify.org?format=json"),e=await t.json(),s=await fetch(`https://ipinfo.io/${e.ip}/json`),o=await s.json(),i={countryCode:o.country,country:o.country,ip:e.ip};return this._lastCountryLookup=i,i}catch(t){return console.error("GeoBlock: Fallback geolocation failed:",t),{countryCode:"XX",country:"Unknown",ip:"Unknown"}}}}async checkAccess(){const t=await this.getCountryInfo(),e=this.blockedCountries.includes(t.countryCode),s=[];return e&&this.config.activePresets.forEach((e=>{this.presets[e]&&this.presets[e].includes(t.countryCode)&&s.push(e)})),{isBlocked:e,countryCode:t.countryCode,country:t.country,ip:t.ip,blockingPresets:s}}applyVisualBlocking(t){document.body.classList.add(this.config.blockingClass);const e=document.createElement("div");e.className=this.config.overlayClass;const s=document.createElement("div");if(s.className=this.config.messageClass,this.config.allowDismiss){const t=document.createElement("div");t.innerHTML="×",t.className="geo-close-btn",t.title="Close",t.addEventListener("click",(()=>this.removeVisualBlocking())),s.appendChild(t);const e={position:"absolute",top:"10px",right:"15px",fontSize:"24px",fontWeight:"bold",color:"#666",cursor:"pointer",lineHeight:"24px",width:"24px",height:"24px",textAlign:"center",borderRadius:"50%",transition:"all 0.2s ease"};Object.assign(t.style,e),this.config.customStyles.closeButton&&Object.assign(t.style,this.config.customStyles.closeButton),t.addEventListener("mouseover",(()=>{t.style.color="#000",t.style.backgroundColor="#f0f0f0"})),t.addEventListener("mouseout",(()=>{t.style.color="#666",t.style.backgroundColor="transparent"}))}const o=document.createElement("div");o.innerHTML=this.formatBlockMessage({...t,blockingPresets:t.blockingPresets||this.computeBlockingPresets(t.countryCode)}),s.appendChild(o);const i={position:"fixed",top:0,left:0,width:"100%",height:"100%",backdropFilter:"blur(10px)",backgroundColor:"rgba(0, 0, 0, 0.5)",zIndex:9998,opacity:0},n={position:"fixed",top:"50%",left:"50%",transform:"translate(-50%, -50%)",padding:"30px",borderRadius:"10px",backgroundColor:"white",color:"#333",maxWidth:"90%",width:"500px",textAlign:"center",boxShadow:"0 5px 30px rgba(0, 0, 0, 0.3)",zIndex:9999,overflowY:"auto",maxHeight:"80vh",opacity:0};Object.assign(e.style,i),Object.assign(s.style,n),this.config.customStyles.overlay&&Object.assign(e.style,this.config.customStyles.overlay),this.config.customStyles.message&&Object.assign(s.style,this.config.customStyles.message),this.config.allowDismiss&&this.config.dismissOnOverlayClick&&(e.addEventListener("click",(()=>this.removeVisualBlocking())),s.addEventListener("click",(t=>t.stopPropagation()))),document.body.appendChild(e),document.body.appendChild(s),setTimeout((()=>{e.style.opacity="0",s.style.opacity="0",setTimeout((()=>{e.style.transition="opacity 0.3s ease",s.style.transition="opacity 0.3s ease",e.style.opacity="1",s.style.opacity="1"}),10)}),50)}formatBlockMessage(t){let e=this.config.blockMessage;e=e.replace(/\{country\}/g,t.country||"Unknown"),e=e.replace(/\{countryCode\}/g,t.countryCode||"XX");let s="";if(t.blockingPresets&&t.blockingPresets.length>0){const e=t.blockingPresets.map((t=>`<li>${this.presetDescriptions[t]||t}</li>`)).join("");s=`\n <p style="margin-top: 15px; font-size: 0.9em; text-align: left;">\n <strong>Restriction Type${t.blockingPresets.length>1?"s":""}:</strong>\n <ul style="margin-top: 5px; padding-left: 20px; text-align: left;">\n ${e}\n </ul>\n </p>\n `}return e+=`\n <div style="margin-top: 20px; font-size: 0.9em; text-align: left;">\n <strong>Important Notice:</strong> We've detected that you're accessing from ${t.country||t.countryCode}. \n ${s}\n <p style="margin-top: 15px;">\n Some features of this site may be restricted or not permitted in your region.\n Please be aware that it is your responsibility to comply with your local laws and regulations.\n Continuing to use this site where prohibited may violate local regulations.\n </p>\n ${this.config.legalEntity?`<p style="margin-top: 15px;">\n ${this.config.legalEntity} bears no liability for any legal consequences that may arise from accessing or using \n this service in jurisdictions where such activities are restricted or prohibited.</p>`:""}\n <p style="margin-top: 15px; font-style: italic;">\n Note: If you believe you're seeing this message in error, please check if you have a VPN \n or proxy service enabled, as this may incorrectly identify your location.\n </p>\n </div>`,e}removeVisualBlocking(){document.body.classList.remove(this.config.blockingClass);const t=document.querySelector("."+this.config.overlayClass),e=document.querySelector("."+this.config.messageClass);t&&t.remove(),e&&e.remove()}async checkAndBlock(){const t=await this.checkAccess();return!t.isBlocked||(this.config.visualBlocking&&this.applyVisualBlocking(t),!1)}getBlockedCountries(){return[...this.blockedCountries]}getPreset(t){return this.presets[t]?[...this.presets[t]]:null}computeBlockingPresets(t){if(!t)return[];const e=[];return this.config.activePresets.forEach((s=>{this.presets[s]&&this.presets[s].includes(t)&&e.push(s)})),e}}}));
//# sourceMappingURL=geoblock.min.js.map