Skip to content

Create unavatools.js#2425

Open
OrangeHub10 wants to merge 1 commit intoTurboWarp:masterfrom
OrangeHub10:patch-1
Open

Create unavatools.js#2425
OrangeHub10 wants to merge 1 commit intoTurboWarp:masterfrom
OrangeHub10:patch-1

Conversation

@OrangeHub10
Copy link

This extension integrates the Unavatar.io API to fetch profile pictures and provides blocks to open social media profiles directly from TurboWarp

This extension integrates the Unavatar.io API to fetch profile pictures and provides blocks to open social media profiles directly from TurboWarp
@github-actions github-actions bot added the pr: new extension Pull requests that add a new extension label Mar 1, 2026
@OrangeHub10
Copy link
Author

Xtras: also, this is made by google AI and me(i also needed to fix code from AI, Also i tried to create code by myself), and THIS MUST RUN UNDSANDBOXED, because of 2 command blocks

@Brackets-Coder
Copy link
Contributor

Xtras: also, this is made by google AI and me(i also needed to fix code from AI, Also i tried to create code by myself), and THIS MUST RUN UNDSANDBOXED, because of 2 command blocks

any extension being added to the gallery runs unsandboxed.

@OrangeHub10
Copy link
Author

@Brackets-Coder YEP!, because of the command blocks, it MUST RUN UNDSANDBOXED, because both uses windows.open

@OrangeHub10
Copy link
Author

also this is the code backup!:(function(Scratch) {
'use strict';

class Unavatar {
getInfo() {
return {
id: 'unavatartools',
name: 'Unavatar Tools',
color1: '#4a4a4a',
color2: '#333333',
blocks: [
{
opcode: 'getProfilePic',
blockType: Scratch.BlockType.REPORTER,
text: 'get pfp unavatar user image with provider [PROVIDER] size [SIZE] user [USERNAME] fallback [FALLBACK]',
arguments: {
PROVIDER: { type: Scratch.ArgumentType.STRING, menu: 'providersMenu', defaultValue: 'github' },
USERNAME: { type: Scratch.ArgumentType.STRING, defaultValue: 'kikobeats' },
SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 },
FALLBACK: { type: Scratch.ArgumentType.STRING, defaultValue: '' }
}
},
{
opcode: 'getAvatarByEmail',
blockType: Scratch.BlockType.REPORTER,
text: 'unavatar of email [EMAIL] size [SIZE]',
arguments: {
EMAIL: { type: Scratch.ArgumentType.STRING, defaultValue: 'hello@microlink.io' },
SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }
}
},
{
opcode: 'getDomainLogo',
blockType: Scratch.BlockType.REPORTER,
text: 'logo of website [DOMAIN] via Google size [SIZE]',
arguments: {
DOMAIN: { type: Scratch.ArgumentType.STRING, defaultValue: 'turbowarp.org' },
SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }
}
},
{
opcode: 'GetDomainLogoNoGoogle',
blockType: Scratch.BlockType.REPORTER,
text: 'Get domain logo [DOMAINLOGO] size [SIZEDOMAINLOGO]',
arguments: {
DOMAINLOGO: { type: Scratch.ArgumentType.STRING, defaultValue: 'hello@microlink.io' },
SIZEDOMAINLOGO: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }
}
},
{
opcode: 'openProfile',
blockType: Scratch.BlockType.COMMAND,
text: 'Open profile of [PROVIDER] user [USERNAME]',
arguments: {
PROVIDER: { type: Scratch.ArgumentType.STRING, menu: 'allProvidersMenu', defaultValue: 'github' },
USERNAME: { type: Scratch.ArgumentType.STRING, defaultValue: 'kikobeats' }
}
},
{
opcode: 'GetProfilePicSize',
blockType: Scratch.BlockType.COMMAND,
text: 'Open unavatar image in new tab [PROVIDERSIZE] user [USERSIZE] size [SIZE]',
arguments: {
PROVIDERSIZE: { type: Scratch.ArgumentType.STRING, menu: 'providersMenu', defaultValue: 'github' },
USERSIZE: { type: Scratch.ArgumentType.STRING, defaultValue: 'kikobeats' },
SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }
}
}
],
menus: {
providersMenu: {
acceptReporters: true,
items: [
'github', 'twitter', 'instagram', 'youtube', 'facebook',
'reddit', 'tiktok', 'twitch', 'soundcloud', 'telegram',
'duckduckgo', 'deviantart', 'dribbble', 'bluesky', 'mastodon', 'threads'
]
},
allProvidersMenu: {
acceptReporters: true,
items: [
'github', 'twitter', 'instagram', 'youtube', 'facebook',
'reddit', 'tiktok', 'twitch', 'soundcloud', 'telegram',
'apple-music', 'spotify', 'patreon'
]
}
}
};
}

_buildUrl(path, size, fallback) {
  const s = size || 400;
  let url = `https://unavatar.io/${path}?size=${s}`;
  if (fallback) {
    url += `&fallback=${encodeURIComponent(fallback)}`;
  }
  return url;
}

getProfilePic(args) {
  const provider = String(args.PROVIDER).toLowerCase().trim();
  const user = encodeURIComponent(args.USERNAME);
  return this._buildUrl(`${provider}/${user}`, args.SIZE, args.FALLBACK);
}

getAvatarByEmail(args) {
  const email = encodeURIComponent(args.EMAIL);
  return this._buildUrl(email, args.SIZE);
}

getDomainLogo(args) {
  const domain = encodeURIComponent(args.DOMAIN);
  return this._buildUrl(`google/${domain}`, args.SIZE);
}

GetDomainLogoNoGoogle(args) {
  const domain = encodeURIComponent(args.DOMAINLOGO);
  return this._buildUrl(domain, args.SIZEDOMAINLOGO);
}

openProfile(args) {
  const provider = String(args.PROVIDER).toLowerCase().trim();
  const userEnc = encodeURIComponent(args.USERNAME);
  
  const profiles = {
    'github': `https://github.com/${userEnc}`,
    'twitter': `https://twitter.com/${userEnc}`,
    'instagram': `https://instagram.com{/$ userEnc}`,
    'youtube': `https://youtube.com/${userEnc}`, 
    'twitch': `https://twitch.tv/${userEnc}`,
    'apple-music': `https://music.apple.com/${userEnc}`,
    'spotify': `https://open.spotify.com/${userEnc}`,
    'patreon': `https://www.patreon.com/${userEnc}`
  };

  const url = profiles[provider] || `https://unavatar.io{provider}/${userEnc}`;
  if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');
}

GetProfilePicSize(args) {
  const url = this.getProfilePic({
    PROVIDER: args.PROVIDERSIZE,
    USERNAME: args.USERSIZE,
    SIZE: args.SIZE,
    FALLBACK: ''
  });
  if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');
}

}

Scratch.extensions.register(new Unavatar());
})(Scratch);

@DELOLCAT
Copy link

DELOLCAT commented Mar 2, 2026

also this is the code backup!:(function(Scratch) {

'use strict';

class Unavatar {

getInfo() {

  return {

    id: 'unavatartools',

    name: 'Unavatar Tools',

    color1: '#4a4a4a',

    color2: '#333333',

    blocks: [

      {

        opcode: 'getProfilePic',

        blockType: Scratch.BlockType.REPORTER,

        text: 'get pfp unavatar user image with provider [PROVIDER] size [SIZE] user [USERNAME] fallback [FALLBACK]', 

        arguments: {

          PROVIDER: { type: Scratch.ArgumentType.STRING, menu: 'providersMenu', defaultValue: 'github' },

          USERNAME: { type: Scratch.ArgumentType.STRING, defaultValue: 'kikobeats' },

          SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 },

          FALLBACK: { type: Scratch.ArgumentType.STRING, defaultValue: '' }

        }

      },

      {

        opcode: 'getAvatarByEmail',

        blockType: Scratch.BlockType.REPORTER,

        text: 'unavatar of email [EMAIL] size [SIZE]',

        arguments: {

          EMAIL: { type: Scratch.ArgumentType.STRING, defaultValue: 'hello@microlink.io' },

          SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }

        }

      },

      {

        opcode: 'getDomainLogo',

        blockType: Scratch.BlockType.REPORTER,

        text: 'logo of website [DOMAIN] via Google size [SIZE]',

        arguments: {

          DOMAIN: { type: Scratch.ArgumentType.STRING, defaultValue: 'turbowarp.org' },

          SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }

        }

      },

      {

        opcode: 'GetDomainLogoNoGoogle',

        blockType: Scratch.BlockType.REPORTER,

        text: 'Get domain logo [DOMAINLOGO] size [SIZEDOMAINLOGO]',

        arguments: {

          DOMAINLOGO: { type: Scratch.ArgumentType.STRING, defaultValue: 'hello@microlink.io' },

          SIZEDOMAINLOGO: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }

        }

      },

      {

        opcode: 'openProfile',

        blockType: Scratch.BlockType.COMMAND,

        text: 'Open profile of [PROVIDER] user [USERNAME]',

        arguments: {

          PROVIDER: { type: Scratch.ArgumentType.STRING, menu: 'allProvidersMenu', defaultValue: 'github' },

          USERNAME: { type: Scratch.ArgumentType.STRING, defaultValue: 'kikobeats' }

        }

      },

      {

        opcode: 'GetProfilePicSize',

        blockType: Scratch.BlockType.COMMAND,

        text: 'Open unavatar image in new tab [PROVIDERSIZE] user [USERSIZE] size [SIZE]',

        arguments: {

          PROVIDERSIZE: { type: Scratch.ArgumentType.STRING, menu: 'providersMenu', defaultValue: 'github' },

          USERSIZE: { type: Scratch.ArgumentType.STRING, defaultValue: 'kikobeats' },

          SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 400 }

        }

      }

    ],

    menus: {

      providersMenu: {

        acceptReporters: true,

        items: [

          'github', 'twitter', 'instagram', 'youtube', 'facebook',

          'reddit', 'tiktok', 'twitch', 'soundcloud', 'telegram',

          'duckduckgo', 'deviantart', 'dribbble', 'bluesky', 'mastodon', 'threads'

        ]

      },

      allProvidersMenu: {

        acceptReporters: true,

        items: [

          'github', 'twitter', 'instagram', 'youtube', 'facebook',

          'reddit', 'tiktok', 'twitch', 'soundcloud', 'telegram',

          'apple-music', 'spotify', 'patreon'

        ]

      }

    }

  };

}



_buildUrl(path, size, fallback) {

  const s = size || 400;

  let url = `https://unavatar.io/${path}?size=${s}`;

  if (fallback) {

    url += `&fallback=${encodeURIComponent(fallback)}`;

  }

  return url;

}



getProfilePic(args) {

  const provider = String(args.PROVIDER).toLowerCase().trim();

  const user = encodeURIComponent(args.USERNAME);

  return this._buildUrl(`${provider}/${user}`, args.SIZE, args.FALLBACK);

}



getAvatarByEmail(args) {

  const email = encodeURIComponent(args.EMAIL);

  return this._buildUrl(email, args.SIZE);

}



getDomainLogo(args) {

  const domain = encodeURIComponent(args.DOMAIN);

  return this._buildUrl(`google/${domain}`, args.SIZE);

}



GetDomainLogoNoGoogle(args) {

  const domain = encodeURIComponent(args.DOMAINLOGO);

  return this._buildUrl(domain, args.SIZEDOMAINLOGO);

}



openProfile(args) {

  const provider = String(args.PROVIDER).toLowerCase().trim();

  const userEnc = encodeURIComponent(args.USERNAME);

  

  const profiles = {

    'github': `https://github.com/${userEnc}`,

    'twitter': `https://twitter.com/${userEnc}`,

    'instagram': `https://instagram.com{/$ userEnc}`,

    'youtube': `https://youtube.com/${userEnc}`, 

    'twitch': `https://twitch.tv/${userEnc}`,

    'apple-music': `https://music.apple.com/${userEnc}`,

    'spotify': `https://open.spotify.com/${userEnc}`,

    'patreon': `https://www.patreon.com/${userEnc}`

  };



  const url = profiles[provider] || `https://unavatar.io{provider}/${userEnc}`;

  if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');

}



GetProfilePicSize(args) {

  const url = this.getProfilePic({

    PROVIDER: args.PROVIDERSIZE,

    USERNAME: args.USERSIZE,

    SIZE: args.SIZE,

    FALLBACK: ''

  });

  if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');

}

}

Scratch.extensions.register(new Unavatar());

})(Scratch);

Mate, just saying, you don't have to add code backups to PR comment sections. GitHub is reliable enough, and event then, the chances of your code becoming corrupted are extremely tiny.

Just a small heads up

@OrangeHub10
Copy link
Author

@DELOLCAT Ok(i'm just preventing the extension to get corrupted but ok)

Comment on lines +1 to +5
// Name: Unavatar tools
// Id: unavatartools
// What it does: it gets unavatar images easily instead of external websites
// includes: 6 blocks, runs unsandboxed because of 2 blocks, doesn't use math, only
// strings, 4 reporters, 2 commands, what it can do, gets url images, opens tabs
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small tip, you may want to replace this header with something like:

// Name: Unavatar Tools
// ID: unavatartools
// Description: Get Unavatar images easily instead of external websites.
// By: OrangeHub10 <https://scratch.mit.edu/users/IF-YOU-HAVE-A-SCRATCH-ACCOUNT-PUT-ITS-USERNAME-HERE/>
// Original: OnlyIfYourExtensionIsAForkOfAnother
// License: MPL-2.0

Your current header is very likely to fail CI.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would tend to agree

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That can be an alternative header(+ i have a scratch account)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That can be an alternative header(+ i have a scratch account)

That header is required to comply with the contributing guidelines.

@kx1xixit
Copy link

kx1xixit commented Mar 6, 2026

@OrangeHub10 i can get you a fast review if you want, I have GitHub Pro so I can request Copilot reviews. It'll give you insights on how to improve your code.

@OrangeHub10
Copy link
Author

@kx1xixit Thanks you! (i did not know about the existance of github pro)( also, my account is like any normal scratcher : https://scratch.mit.edu/users/orangescratcher9/ )

@kx1xixit
Copy link

kx1xixit commented Mar 7, 2026

@copilot review

@kx1xixit
Copy link

kx1xixit commented Mar 7, 2026

Dang, nevermind. I might need contributor permissions to assign Copilot as a reviewer, so nevermind lol

@OrangeHub10
Copy link
Author

@kx1xixit its ok, i think i dont need to change the code, its already enough with the code, let the code be like that(this is like the second extension i have made with ai and me) so yeah.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: new extension Pull requests that add a new extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants