• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

javascript's "do script" documentation for Aia no gui

Explorer ,
Aug 04, 2017 Aug 04, 2017

Copy link to clipboard

Copied

Hi,

I'm leeching Adobe's and Stack Exchange's forums, but I can't find any recent post about this specific command:

           app.executeMenuCommand('ai_browse_for_script');

I want to run a action script on a batch of files without User Interaction, only jsx file - So this CMD needs more parameters like PATH and NODISPLAY. NB: this cmd showed up since CS6

It is not in guides CS6 nor CC2017 (we already knew that) So it's not present into Jongware's fantastic CHM reference guide; The best guide about menuExecCMD I've found so far is http://chuwa.iobb.net/tech/illustrator-cc2014-menu-comman.html

Maybe noone is using this which I highly doubt; the only documented workaround seems to doscript from VB which is something I could do, but I was focusing JSX for now.

So I will run something like this:

#target Illustrator-21

#targetengine main

var scriptID = "test-doscript v0.0";

var sourceFolder1 = null;

var fileType = null;

var files1  = null;

var sourceFolder1 = Folder ("C:/TEMPai/F1");

var fileType = "*.pdf";

var originalInteractionLevel = userInteractionLevel;
userInteractionLevel
= UserInteractionLevel.DONTDISPLAYALERTS;

     files1 = new Array();

     files1 = sourceFolder1.getFiles( fileType );

      if ( files1.length != 0 ){

          for ( i = 0; i < files1.length; i++ ){

               var sourceDoc1 = app.open(files1);

               app.executeMenuCommand('ai_browse_for_script');

          }

     }

I'm looking for the equivalent of this - NB: I don't car about errors as I debug them myself. I doing things 1 by 1, nowadays I [think to] know what I'm doing.

Thank you for your time, maybe my google-fu is stuck. Overall this is very important to have a complete control about what illustrator do, because I can manage keeping ram usage low with the For {} loop, indeed I can't save save my work until the otherwise I'll loose hours a day waiting Ai to save files

Possible workaround? Could I copy paste aia into jsx file? https://gist.github.com/moluapple/2568405

EDIT: app.executeMenuCommand('ai_browse_for_script';script1); is not syntax-correct

EDIT2 app.executeMenuCommand('ai_browse_for_script') is requesting vb or jsx file extension only

Image: This is the screen I want to get rid off keeping the same idea, instead there I will make the batch myself

Message was edited by: et3d Updated edit

TOPICS
Scripting

Views

4.8K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Enthusiast , Aug 11, 2017 Aug 11, 2017

You don't need to use "try...catch" statement like what I had done,

change

try {  

  app.doScript(action, set); // first run because the action does not exist and pop-up dialog box, click Stop to create the action, do not point to continue  

} catch(e) {  

  createAction(actionStr, set);  

  app.doScript(action, set);  

}  

to

createAction(actionStr, set);  

app.doScript(action, set);

app.unloadAction (set, '');

Votes

Translate

Translate
Adobe
Valorous Hero ,
Aug 04, 2017 Aug 04, 2017

Copy link to clipboard

Copied

I know you want to get rid of batch dialog, but...
You can put in a script into your File / Scripts menu and then have your action play that script. Adobe says they fixed the bug now which used to happen when Actions would 'forget' the script that was recorded into them.

So now you can just do batch actions and play your custom script on each file relatively easily. Since it's a custom script and it has to be installed in your Illustrator's application presets / scripts folder, wherever that's at, and it only shows up in the File > Scripts menu after Illustrator is restarted, having many different scripts in there could be cumbersome. However since it's a customs script, you can make it generic for your purposes and run off some arguments, such as a text file on your desktop, etc, in order to play various different functions by means of the one menu script.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 07, 2017 Aug 07, 2017

Copy link to clipboard

Copied

Thanks, yes I'm actively using it every day I want to go further. Is it possible to simply run Aia into Jsx?

I want to fit my Aia into Moluapple's JS script:

My Aia: https://gist.github.com/et3d/c7c08327404c39cbfeecd35ea25a46aa

Moluapple's JS to Aia script translated to EN: https://gist.github.com/moluapple/2568405

// CS6 only

var set = 'Script Action', // action set name

  action = 'PastePDF', // action name

  menuEn = 'paste', // menu English

  menuZh = '粘贴', // menu Chinese

  actionStr = ['/version 3',

  '/name [ ' + set.length,

  ascii2Hex(set),

  ']',

  '/isOpen 0',

  '/actionCount 1',

  '/action-1 {',

  '/name [ ' + action.length,

  ascii2Hex(action),

  ']',

  '/keyIndex 0',

  '/colorIndex 0',

  '/isOpen 1',

  '/eventCount 1',

  '/event-1 {',

  '/useRulersIn1stQuadrant 0',

  '/internalName (adobe_commandManager)',

  '/localizedName [ 15',

  'e8aebfe997aee88f9ce58d95e9a1b9',

  ']',

  '/isOpen 0',

  '/isOn 1',

  '/hasDialog 0',

  '/parameterCount 3',

  '/parameter-1 {',

  '/key 1769238125',

  '/showInPalette -1',

  '/type (ustring)',

  '/value [ ' + menuEn.length,

  ascii2Hex(menuEn),

  ']',

  '}',

  '/parameter-2 {',

  '/key 1818455661',

  '/showInPalette -1',

  '/type (ustring)',

  '/value [ ' + menuZh.length * 3,

  GBK2Hex(menuZh),

  ']',

  '}',

  '/parameter-3 {',

  '/key 1668114788',

  '/showInPalette -1',

  '/type (integer)',

  '/value 1885434740',

  '}',

  '}',

  '}'].join('\n');

try {

  app.doScript(action, set); // first run because the action does not exist and pop-up dialog box, click Stop to create the action, do not point to continue

} catch(e) {

  createAction(actionStr, set);

  app.doScript(action, set);

}

function createAction (str, set) {

  var f = File(set + '.aia');

  f.open('w');

  f.write(str);

  f.close();

  app.loadAction(f);

  f.remove();

}

function ascii2Hex (hex) {

  return hex.replace(/./g, function (a) {return a.charCodeAt(0).toString(16)})

}

function GBK2Hex (str/* Chinese characters*/) {

  var f = File('hex.txt'), hex;

  f.encoding = 'UTF8';

  f.open('w'), f.write(str), f.close();

  f.encoding = 'BINARY';

  f.open('r');

  hex = f.read().toSource().replace(/(?:\(new String\("|"\)\)|\\u00)/g, '');

  f.close(), f.remove();

  return hex

}

As you can see there is a hex conversion for some "command id" to understand what Aia is doing

It could be a begining of a solution what do you think?

es I f

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Aug 07, 2017 Aug 07, 2017

Copy link to clipboard

Copied

Yes, that's how it's done.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 10, 2017 Aug 10, 2017

Copy link to clipboard

Copied

Why I want to use AiA?

2 reasons: technically I don't have enough JSX snippets for the whole process. Then for my pre-process of a bunch of pdf files ActionScripts actually works. ((I'm still coding following this idea))

((Btw big thank you Silly-V and moluapple , I've just made jsx snippet "search string and replace" that works based on yours contributions and learned what is RegEx on the way ; ) ))

Scrapping wha'ts existing:

I'm trying to figure out how Moluapple's script is working with hex translation thing. And what the the ActionScript does.

I feel that this conversion may be a good tip. I do know remember reading it but I don't know where.

What I've understood:

The JavaScript creates a new action on the first run - there might be an error here so the author uses catch(e) but I don't get why -  creating the action is a whole function process. Once the action exists into Illustrator it can be called using doscript() method

The script stops at line This updated stand alone version pop up an error about the action script cannot be executed which sound good

app.doScript(action, set); // first run because the action does not exist and pop-up dialog box, click Stop to create the action, do not point to continue

Other thing that I don't understand is why the author use 2 parameters for action script's Event's Value like here

  '/value [ ' + menuZh.length * 3, GBK2Hex(menuZh),  ]

On my Action script I only see "/Value 1"

This is the code​ on gist

Updated ie the current version : what I am missing?

#target Illustrator-21

#targetengine main

var sourceFolder1 = Folder ("C:/TEMPai/y.test"); //only 1 file

openfile_selectallartworks();

if ( activeDocument.selection.length > 0 ) {

    moluapples_code();

}

function openfile_selectallartworks(){

var fileType = "*.pdf";

files1 = new Array();

files1 = sourceFolder1.getFiles( fileType );

if ( files1.length != 0 ){

    var sourceDoc1 = app.open(files1[0]);

    for (l = 0; l < sourceDoc1.pageItems.length-1; l++) {     //pageItems  L

        sourceDoc1.pageItems.selected = true;               

    }

}

}

function moluapples_code(){   

var set = 'Action resize10', // action set name

action = 'adobe_scale' //there gonna be an issue bcs here I have 2 events, M uses only 1 

var actionStr = ['/version 3',

  '/name [ ' + set.length, 

  ascii2Hex(set),

']',

'/isOpen 1',

'/actionCount 1',

'/action-1 {',

'    /name [ ' + action.length, 

  ascii2Hex(action), 

  ']',

'    /keyIndex 0',

'    /colorIndex 0',

'    /isOpen 1',

'    /eventCount 3',

'    /event-1 {',                //ACTION1: Resize selection to 10%

'        /useRulersIn1stQuadrant 0',

'        /internalName (adobe_scale)',

'        /localizedName [ 18',

'            4d69736520c3a0206c27c3a96368656c6c65',

'        ]',

'        /isOpen 1',

'        /isOn 1',

'        /hasDialog 1',

'        /showDialog 0',

'        /parameterCount 4',

'        /parameter-1 {',

'            /key 1970169453',

'            /showInPalette -1',

'            /type (boolean)',

'            /value 1',

'        }',

'        /parameter-2 {',

'            /key 1818848869',

'            /showInPalette -1',

'            /type (boolean)',

'            /value 1',

'        }',

'        /parameter-3 {',

'            /key 1935895653',

'            /showInPalette -1',

'            /type (unit real)',

'            /value 10.0',

'            /unit 592474723',

'        }',

'        /parameter-4 {',

'            /key 1668247673',

'            /showInPalette -1',

'            /type (boolean)',

'            /value 0',

'        }',

'    }',

'    /event-2 {',                                    //ACTION2 borders limits

'        /useRulersIn1stQuadrant 0',

'        /internalName (adobe_commandManager)', //10% resize workarea to selected artwork; this should go around 87.5*280mm

'        /localizedName [ 32',

'            416363c3a964657220c3a020756e6520636f6d6d616e6465206465206d656e75',

'        ]',

'        /isOpen 0',

'        /isOn 1',

'        /hasDialog 0',

'        /parameterCount 3',

'        /parameter-1 {',

'            /key 1769238125',

'            /showInPalette -1',

'            /type (ustring)',

'            /value [ 28',

'                46697420417274626f61726420746f2073656c656374656420417274',

'            ]',

'        }',

'        /parameter-2 {',

'            /key 1818455661',

'            /showInPalette -1',

'            /type (ustring)',

'            /value [ 40',

'                416a757374657220c3a0206c27696c6c757374726174696f6e2073c3a96c6563',

'                74696f6e6ec3a965',

'            ]',

'        }',

'        /parameter-3 {',

'            /key 1668114788',

'            /showInPalette -1',

'            /type (integer)',

'            /value -2130706017',

'        }',

'    }',

'}'].join('\n'); 

try { 

  app.doScript(action, set); // first run because the action does not exist and pop-up dialog box, click Stop to create the action, do not point to continue 

} catch(e) { 

  createAction(actionStr, set); 

  app.doScript(action, set); 

}

}//moluapples_code main end 

 

function createAction (str, set) { 

  var f = File(set + '.aia'); 

  f.open('w'); 

  f.write(str); 

  f.close(); 

  app.loadAction(f); 

  f.remove(); 

 

function ascii2Hex (hex) { 

  return hex.replace(/./g, function (a) {return a.charCodeAt(0).toString(16)}) 

I use 2 events, only 1 is defined using  action = 'adobe_scale'...

Besides my variables declaration might be problematic, I use to restart Ai and Estk for that purpose

Updated  The script does create a new actionscript error which rocks!!! but then is says error: can't do 'execute the script'. I think I've ran out of coffee and I 've started coding with my feet

Errors Outputs:

"The object "Execute the script" is not available now" I choose stop because it gives new errors : D

"Impossible to load the action scripts, the document does not comply" There seems to be some kind of method error into the action script code

"Impossible to run the script into the target engine 'main'! " This seems to be a rather serious issue??

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Aug 10, 2017 Aug 10, 2017

Copy link to clipboard

Copied

If the text produced by your code as aia file can be manually importer into the Actions panel, so it should do so via the script. Test your aia by trying to manually load them and see the result. If everything looks 100% good, there may be some problem which you can troubleshoot by creating other versions of this action manually and comparing them with your script-created actions to find exactly why they are not working.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

I've got an issue, I can't (don't know how) debug functions, but if I don't use fonctions, variables try to go into hyperspace

I got these errors on Moluapple script too

#target Illustrator-21

var set = 'Script Action', // action set name

  action = 'PastePDF', // action name

  menuEn = 'paste', // menu English

  menuZh = '粘贴', // menu Chinese

  actionStr = ['/version 3',

  '/name [ ' + set.length,

  ascii2Hex(set),

  ']',

  '/isOpen 0',

  '/actionCount 1',

  '/action-1 {',

  '/name [ ' + action.length,

  ascii2Hex(action),

  ']',

  '/keyIndex 0',

  '/colorIndex 0',

  '/isOpen 1',

  '/eventCount 1',

  '/event-1 {',

  '/useRulersIn1stQuadrant 0',

  '/internalName (adobe_commandManager)',

  '/localizedName [ 15',

  'e8aebfe997aee88f9ce58d95e9a1b9',

  ']',

  '/isOpen 0',

  '/isOn 1',

  '/hasDialog 0',

  '/parameterCount 3',

  '/parameter-1 {',

  '/key 1769238125',

  '/showInPalette -1',

  '/type (ustring)',

  '/value [ ' + menuEn.length,

  ascii2Hex(menuEn),

  ']',

  '}',

  '/parameter-2 {',

  '/key 1818455661',

  '/showInPalette -1',

  '/type (ustring)',

  '/value [ ' + menuZh.length * 3,

  GBK2Hex(menuZh),

  ']',

  '}',

  '/parameter-3 {',

  '/key 1668114788',

  '/showInPalette -1',

  '/type (integer)',

  '/value 1885434740',

  '}',

  '}',

  '}'].join('\n');

try {

  app.doScript(action, set); // first run because the action does not exist and pop-up dialog box, click Stop to create the action, do not point to continue

} catch(e) {

  createAction(actionStr, set);

  app.doScript(action, set);

}

function createAction (str, set) {

  var f = File(set + '.aia');

  f.open('w');

  f.write(str);

  f.close();

  app.loadAction(f);

  f.remove();

}

function ascii2Hex (hex) {

  return hex.replace(/./g, function (a) {return a.charCodeAt(0).toString(16)})

}

function GBK2Hex (str/* Chinese characters*/) {

  var f = File('hex.txt'), hex;

  f.encoding = 'UTF8';

  f.open('w'), f.write(str), f.close();

  f.encoding = 'BINARY';

  f.open('r');

  hex = f.read().toSource().replace(/(?:\(new String\("|"\)\)|\\u00)/g, '');

  f.close(), f.remove();

  return hex

}

Script stops line 57

Reading your thread ... So you can use RegEx to quote the AiA ( :

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

#target Illustrator-21

var set = 'action_resize10', // action set name

  action = 'resize', // action name

  menuEn = 'adobe_scale', // menu English ???????

  actionStr = ['/version 3',

'/name [ 15',

'    616374696f6e5f726573697a653130',                //action_resize10

']',

'/isOpen 1',

'/actionCount 1',

'/action-1 {',

    '/name [ 6',

        '726573697a65',                            //resize

    ']',

    '/keyIndex 0',

    '/colorIndex 0',

    '/isOpen 1',

    '/eventCount 1',

    '/event-1 {',

        '/useRulersIn1stQuadrant 0',

        '/internalName (adobe_scale)',

        '/localizedName [ 18',

            '4d69736520c3a0206c27c3a96368656c6c65', //mise a l'echelle/scale

        ']',

        '/isOpen 0',

        '/isOn 1',

        '/hasDialog 1',

        '/showDialog 0',

        '/parameterCount 4',

        '/parameter-1 {',

            '/key 1970169453',

            '/showInPalette -1',

            '/type (boolean)',

            '/value 1',

        '}',

        '/parameter-2 {',

            '/key 1818848869',

            '/showInPalette -1',

            '/type (boolean)',

            '/value 1',

        '}',

        '/parameter-3 {',

            '/key 1935895653',

            '/showInPalette -1',

            '/type (unit real)',

            '/value 10.0',                            //Should be the 10%

            '/unit 592474723',

        '}',

        '/parameter-4 {',

            '/key 1668247673',

            '/showInPalette -1',

            '/type (boolean)',

            '/value 0',

        '}',

    '}',

'}'].join('\n');

try {

  app.doScript(action, set); // first run because the action does not exist and pop-up dialog box, click Stop to create the action, do not point to continue

} catch(e) {

  createAction(actionStr, set);

  app.doScript(action, set);

}

function createAction (str, set) {

  var f = File(set + '.aia');

  f.open('w');

  f.write(str);

  f.close();

  app.loadAction(f);

  //f.remove();                                            The script doesn't add itself to the action list : /

}

function ascii2Hex (hex) {

  return hex.replace(/./g, function (a) {return a.charCodeAt(0).toString(16)})

}

This is the simplest version I can put. - it only scales down to 10 % the selection - I just don't get it working 😕 same errors "Continue/Stop"

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

This is the code on gist

Updated ie the current version : what I am missing?

Hi, in your code line 39:

'    /eventCount 3',

But there are only 2 events in the action, so please change it to :

'    /eventCount 2',

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

  1. function createAction (str, set) { 
  2. var f = File(set + '.aia'); 
  3.   f.open('w'); 
  4.   f.write(str);
  5.   f.close();
  6.   app.loadAction(f);
  7. //f.remove();                                            The script doesn't add itself to the action list : / 
  8. }

=> function createAction (action, set) {

  f.write(str) => f.write(actionStr)

It seems to fail at the script creation step (it pop up briefly into the panel), because app.doscript(action, set) works if the action script is in the action panel

Thanks you're right, I've been reducing the code - At least I can manage to do more stuff with what I've learnt from your code

I'm running the code line by line with F10 in ESTK but strings and functions are not read that way

Edit: I have updated ESTK to the CC version so it's now v4.5 but issues persist

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

You don't need to use "try...catch" statement like what I had done,

change

try {  

  app.doScript(action, set); // first run because the action does not exist and pop-up dialog box, click Stop to create the action, do not point to continue  

} catch(e) {  

  createAction(actionStr, set);  

  app.doScript(action, set);  

}  

to

createAction(actionStr, set);  

app.doScript(action, set);

app.unloadAction (set, '');

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

Cannot load action script, indeed the doc isn't compatible

function createAction (actionStr, set) {

  var f = new File(set + '.aia');

  f.open('w');

  f.write(actionStr);

  f.close();

  app.loadAction(f);               //LINE 75

  f.remove();

}

Thank you! This has gone further

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

Updated Ok I've managed to load the f action set "action_script1" into actions panel... which is marvelous!!!

Besides if I use the action is does what it is designed to do, ie scaling down to 10%

I forgot to edit "action" and "set" variables-names into the "actionStr" string! : S

Here is the code following your very wise advises:

#target Illustrator-21

var set = 'script_action1'; // action set name 

var action = 'scale10'; // action name 

var actionStr = ['/version 3',

'/name [ 15',

'    616374696f6e5f726573697a653130',                //action_resize10

']',

'/isOpen 1',

'/actionCount 1',

'/action-1 {',

    '/name [ 6',

        '726573697a65',                             //resize

    ']',

    '/keyIndex 0',

    '/colorIndex 0',

    '/isOpen 1',

    '/eventCount 1',

    '/event-1 {',

        '/useRulersIn1stQuadrant 0',

        '/internalName (adobe_scale)',

        '/localizedName [ 18',

            '4d69736520c3a0206c27c3a96368656c6c65', //mise a l'echelle/scale

        ']',

        '/isOpen 0',

        '/isOn 1',

        '/hasDialog 1',

        '/showDialog 0',

        '/parameterCount 4',

        '/parameter-1 {',

            '/key 1970169453',

            '/showInPalette -1',

            '/type (boolean)',

            '/value 1',

        '}',

        '/parameter-2 {',

            '/key 1818848869',

            '/showInPalette -1',

            '/type (boolean)',

            '/value 1',

        '}',

        '/parameter-3 {',

            '/key 1935895653',

            '/showInPalette -1',

            '/type (unit real)',

            '/value 10.0',                            //Should be the 10%

            '/unit 592474723',

        '}',

        '/parameter-4 {',

            '/key 1668247673',

            '/showInPalette -1',

            '/type (boolean)',

            '/value 0',

        '}',

    '}',

'}'].join('\n');

createAction(actionStr, set);    

app.doScript(action, set);  

app.unloadAction (set, '');                                                //hangs here for now

 

function createAction (actionStr, set) { 

  var fpath = Folder ("C:/TEMPai/y.script/script-test/anothertest")        //normal path is inside programfiles

  var f = File(fpath + set + '.aia'); 

  f.open('w'); 

  f.write(actionStr); 

  f.close(); 

  app.loadAction(f); 

  f.remove(); 

 

function ascii2Hex (hex) { 

  return hex.replace(/./g, function (a) {return a.charCodeAt(0).toString(16)}) 

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 11, 2017 Aug 11, 2017

Copy link to clipboard

Copied

LATEST

Thank you for your patience - Now I feel the power of action_scripts!

You guys deserve respect!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines