Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Hivescript

An open standard for Hive based apps.

  • Apps - URL format and canonical linking schemes
  • BadActors - accounts mischiefs or phishing attempts
  • BadDomains - phishing domains
  • GoodDomains - domains known to be safe
  • Spaminator - larger imported lists maintained by the Spaminator project

How to use this package

yarn add @hiveio/hivescript

Files

FileShapeWhat it is
apps.jsonobjectApp registry: display name, homepage and canonical url_scheme
bad-actors.jsonstring[]Accounts reported for phishing / typosquatting exchange names
bad-domains.jsonstring[]Phishing domains, curated
good-domains.jsonstring[]Domains known to be safe
spaminator-domains.jsonstring[]Domain blocklist imported from Spaminator
spaminator-all.jsonstring[]Full Spaminator account blocklist (~174k entries, 2 MB)

spaminator-all.json is large. Import it only if you actually need it, and never into a browser bundle.

Canonical linking

On Hive, content is stored in blockchain and same information is accessible via different websites and services built on Hive. Canonical linking to origin of post is important for entire ecosystem to thrive.

Two things about apps.json decide the shape of the code below:

  • url_scheme is optional. Some entries are publishing tools with no web home of their own (beempy, steempress). Reading .url_scheme off those gives undefined, so always fall back to your own scheme rather than assuming it is there.
  • Not every scheme uses {category}. A scheme may contain {category}, {username} and {permlink} in any combination. Replace whatever is present and leave the rest alone.
importappsfrom"@hiveio/hivescript/apps.json";// Your own site's scheme, used whenever the post's app is unknown to us.constDEFAULT_SCHEME="https://example.com/{category}/@{username}/{permlink}";functioncanonicalLink(entry,defaultScheme=DEFAULT_SCHEME){// json_metadata is an object on bridge.* but a JSON string on condenser_api.*letmeta=entry.json_metadata;if(typeofmeta==="string"){try{meta=JSON.parse(meta);}catch{meta={};}}// `app` is normally "ecency/3.1.4" but some apps write an object instead. Neither form// is guaranteed: json_metadata is arbitrary author-supplied JSON, so check the type// before calling string methods on it.constapp=meta?.app;constraw=typeofapp==="string" ? app : app?.name;constidentifier=typeofraw==="string" ? raw.split("/")[0].trim().toLowerCase() : undefined;// Falls back when the app is unknown OR known but has no url_scheme of its own.constscheme=(identifier&&apps[identifier]?.url_scheme)||defaultScheme;returnscheme.replace("{category}",entry.category).replace("{username}",entry.author).replace("{permlink}",entry.permlink);}

Contributing

node scripts/validate.mjs checks every data file: shape, sorting, duplicates, casing, good/bad overlap, public suffixes and apps.json placeholders. CI runs it on every pull request and again before publish. No dependencies to install.

The public suffix check reads scripts/public-suffix-list.txt, a snapshot of the Public Suffix List refreshed by node scripts/update-public-suffix-list.mjs. That snapshot is MPL 2.0, carries its upstream notice, and is development tooling only: it is outside the files allowlist, so the npm package stays MIT.

Adding or changing an app

Open a pull request against apps.json. Entries are sorted by key. A url_scheme must be https, must contain {permlink}, and must resolve to a real post page: no hash fragments (#!/...), because search engines do not treat those as distinct canonical URLs. Entries whose domain stops resolving, starts redirecting off-site or gets parked are removed, since a stale entry sends every frontend's canonical links and the SEO authority behind them to whoever holds the domain now.

Bad actors

Bad actors, list of account that is mostly created with intention to take advantage of user mistype. Sometimes simple misspell can direct funds into wrong accounts, this list contain those reported accounts.

This section could be part of wallet page in your Dapp where user enters account name to transfer funds to.

Build a Set once at module load. The list is over a thousand entries and Array.includes re-scans all of it on every keystroke.

importbadActorsfrom"@hiveio/hivescript/bad-actors.json";constBAD_ACTORS=newSet(badActors);// Hive account names are lowercase; normalise before comparing.if(BAD_ACTORS.has(to_account.trim().toLowerCase().replace(/^@/,""))){console.warn("Use caution sending to this account. Please double check your spelling for possible phishing.");}

Bad domains

Phishing domains, list of phishing domains, we recommend Dapp/frontend developers check external link clicks and warn users about potential phishing domains.

This section could be part of content rendering or external link clicking event listener in your web/mobile/desktop apps.

Parse the URL rather than matching it with a regex. new URL() lowercases the host and converts internationalised domains to punycode, which is what the list stores, so homograph domains such as șteemit.com (xn--teemit-2lc.com) are caught. Then walk the parent domains, otherwise login.phishing-site.tk slips past an entry for phishing-site.tk.

Because consumers walk parent domains, every entry in these lists has to be a registrable domain. A public suffix such as web.app, github.io or co.uk would condemn every site hosted under it, so list the specific abusive hostname instead. CI rejects entries that are public suffixes.

importbadDomainsfrom"@hiveio/hivescript/bad-domains.json";constBAD_DOMAINS=newSet(badDomains);functionisBadDomain(externalLink){lethost;try{// A terminal dot is a valid, fully qualified host: browsers resolve// "steemit24.cf." exactly like "steemit24.cf", so strip it before matching.host=newURL(externalLink).hostname.toLowerCase().replace(/\.$/,"").replace(/^www\./,"");}catch{returnfalse;// not a URL we can judge}// "a.b.evil.tk" -> checks "a.b.evil.tk", "b.evil.tk", "evil.tk"constlabels=host.split(".");returnlabels.some((_,i)=>BAD_DOMAINS.has(labels.slice(i).join(".")));}if(isBadDomain(external_link)){console.warn("Security alert! Site ahead contains malware / Suspected phishing page.");}

new URL() needs an absolute URL. If you are checking hrefs straight out of post bodies, resolve them first: new URL(href, "https://example.com").

Contributors

Hive community

About

@hiveio/hivescript

Topics

Resources

Stars

8 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages