Utils.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. import { Chance } from 'chance';
  2. import { JSFuck } from './enums/JSFuck';
  3. const isEqual = require('is-equal');
  4. export class Utils {
  5. /**
  6. * @type {string}
  7. */
  8. public static readonly hexadecimalPrefix: string = '0x';
  9. /**
  10. * @type {string}
  11. */
  12. public static readonly randomGeneratorPool: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  13. /**
  14. * @type {string}
  15. */
  16. public static readonly randomGeneratorPoolWithNumbers: string = `${Utils.randomGeneratorPool}0123456789`;
  17. /**
  18. * @type {Chance.Chance | Chance.SeededChance}
  19. */
  20. private static randomGenerator: Chance.Chance | Chance.SeededChance = new Chance();
  21. /**
  22. * @param array
  23. * @param searchElement
  24. * @returns {boolean}
  25. */
  26. public static arrayContains (array: any[], searchElement: any): boolean {
  27. return array.indexOf(searchElement) >= 0;
  28. }
  29. /**
  30. * @param array
  31. * @param times
  32. * @returns {T[]}
  33. */
  34. public static arrayRotate <T> (array: T[], times: number): T[] {
  35. if (!array.length) {
  36. throw new ReferenceError(`Cannot rotate empty array.`);
  37. }
  38. if (times <= 0) {
  39. return array;
  40. }
  41. let newArray: T[] = array,
  42. temp: T | undefined;
  43. while (times--) {
  44. temp = newArray.pop()!;
  45. newArray.unshift(temp);
  46. }
  47. return newArray;
  48. }
  49. /**
  50. * @param string
  51. */
  52. public static btoa (string: string): string {
  53. const chars: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  54. let output: string = '';
  55. string = encodeURIComponent(string).replace(/%([0-9A-F]{2})/g, (match, p1) => {
  56. return String.fromCharCode(parseInt(`${Utils.hexadecimalPrefix}${p1}`));
  57. });
  58. for (
  59. let block: number|undefined, charCode: number, idx: number = 0, map: string = chars;
  60. string.charAt(idx | 0) || (map = '=', idx % 1);
  61. output += map.charAt(63 & block >> 8 - idx % 1 * 8)
  62. ) {
  63. charCode = string.charCodeAt(idx += 3/4);
  64. if (charCode > 0xFF) {
  65. throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
  66. }
  67. block = block << 8 | charCode;
  68. }
  69. return output;
  70. }
  71. /**
  72. * @param dec
  73. * @returns {string}
  74. */
  75. public static decToHex (dec: number): string {
  76. const radix: number = 16;
  77. return Number(dec).toString(radix);
  78. }
  79. /**
  80. * @param url
  81. * @returns {string}
  82. */
  83. public static extractDomainFromUrl (url: string): string {
  84. let domain: string;
  85. if (url.indexOf('://') > -1 || url.indexOf('//') === 0) {
  86. domain = url.split('/')[2];
  87. } else {
  88. domain = url.split('/')[0];
  89. }
  90. domain = domain.split(':')[0];
  91. return domain;
  92. }
  93. /**
  94. * @param min
  95. * @param max
  96. * @returns {number}
  97. */
  98. public static getRandomFloat (min: number, max: number): number {
  99. return Utils.randomGenerator.floating({
  100. min: min,
  101. max: max,
  102. fixed: 7
  103. });
  104. }
  105. /**
  106. * @returns {Chance.Chance}
  107. */
  108. public static getRandomGenerator (): Chance.Chance {
  109. const randomGenerator: Chance.Chance = Utils.randomGenerator;
  110. if (!randomGenerator) {
  111. throw new Error(`\`randomGenerator\` static property is undefined`);
  112. }
  113. return Utils.randomGenerator;
  114. }
  115. /**
  116. * @param min
  117. * @param max
  118. * @returns {number}
  119. */
  120. public static getRandomInteger (min: number, max: number): number {
  121. return Utils.randomGenerator.integer({
  122. min: min,
  123. max: max
  124. });
  125. }
  126. /**
  127. * @param length
  128. * @returns {string}
  129. */
  130. public static getRandomVariableName (length: number = 6): string {
  131. const rangeMinInteger: number = 10000,
  132. rangeMaxInteger: number = 99999999;
  133. return `_${Utils.hexadecimalPrefix}${(
  134. Utils.decToHex(
  135. Utils.getRandomInteger(rangeMinInteger, rangeMaxInteger)
  136. )
  137. ).substr(0, length)}`;
  138. }
  139. /**
  140. * @param str
  141. * @param length
  142. * @returns {string[]}
  143. */
  144. public static hideString(str: string, length: number): [string, string] {
  145. const escapeRegExp: (s: string) => string = (s: string) =>
  146. s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
  147. const randomMerge: (s1: string, s2: string) => string = function (s1: string, s2: string): string {
  148. let i1: number = -1,
  149. i2: number = -1,
  150. result: string = '';
  151. while (i1 < s1.length || i2 < s2.length) {
  152. if (Utils.getRandomFloat(0, 1) < 0.5 && i2 < s2.length) {
  153. result += s2.charAt(++i2);
  154. } else {
  155. result += s1.charAt(++i1);
  156. }
  157. }
  158. return result;
  159. };
  160. const randomString: string = Utils.randomGenerator.string({
  161. length: length,
  162. pool: Utils.randomGeneratorPool
  163. });
  164. let randomStringDiff: string = randomString.replace(
  165. new RegExp('[' + escapeRegExp(str) + ']', 'g'),
  166. '');
  167. const randomStringDiffArray: string[] = randomStringDiff.split('');
  168. Utils.randomGenerator.shuffle(randomStringDiffArray);
  169. randomStringDiff = randomStringDiffArray.join('');
  170. return [randomMerge(str, randomStringDiff), randomStringDiff];
  171. }
  172. /**
  173. * @param number
  174. * @returns {boolean}
  175. */
  176. public static isInteger (number: number): boolean {
  177. return number % 1 === 0;
  178. }
  179. /**
  180. * @param map
  181. * @param value
  182. * @returns {any}
  183. */
  184. public static mapGetFirstKeyOf(map: Map <any, any>, value: any): any {
  185. for (var [key, storageValue] of map) {
  186. if (isEqual(value, storageValue)) {
  187. return key;
  188. }
  189. }
  190. return null;
  191. }
  192. /**
  193. * RC4 symmetric cipher encryption/decryption
  194. * https://gist.github.com/farhadi/2185197
  195. *
  196. * @param key
  197. * @param string
  198. * @returns {string}
  199. */
  200. public static rc4 (string: string, key: string) {
  201. let s: number[] = [],
  202. j: number = 0,
  203. x: number,
  204. result: string = '';
  205. for (var i = 0; i < 256; i++) {
  206. s[i] = i;
  207. }
  208. for (i = 0; i < 256; i++) {
  209. j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
  210. x = s[i];
  211. s[i] = s[j];
  212. s[j] = x;
  213. }
  214. i = 0;
  215. j = 0;
  216. for (let y = 0; y < string.length; y++) {
  217. i = (i + 1) % 256;
  218. j = (j + s[i]) % 256;
  219. x = s[i];
  220. s[i] = s[j];
  221. s[j] = x;
  222. result += String.fromCharCode(string.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
  223. }
  224. return result;
  225. }
  226. /**
  227. * @param randomGeneratorSeed
  228. */
  229. public static setRandomGeneratorSeed (randomGeneratorSeed: number): void {
  230. Utils.randomGenerator = new Chance(randomGeneratorSeed);
  231. }
  232. /**
  233. * @param obj
  234. * @returns {T}
  235. */
  236. public static strEnumify <T extends {[prop: string]: ''|string}> (obj: T): T {
  237. return obj;
  238. }
  239. /**
  240. * @param string
  241. * @returns {string}
  242. */
  243. public static stringToJSFuck (string: string): string {
  244. return Array
  245. .from(string)
  246. .map((character: string): string => {
  247. return JSFuck[character] || character;
  248. })
  249. .join(' + ');
  250. }
  251. /**
  252. * @param string
  253. * @returns {string}
  254. */
  255. public static stringToUnicodeEscapeSequence (string: string): string {
  256. const radix: number = 16;
  257. let prefix: string,
  258. regexp: RegExp = new RegExp('[\x00-\x7F]'),
  259. template: string;
  260. return `${string.replace(/[\s\S]/g, (escape: string): string => {
  261. if (regexp.test(escape)) {
  262. prefix = '\\x';
  263. template = '0'.repeat(2);
  264. } else {
  265. prefix = '\\u';
  266. template = '0'.repeat(4);
  267. }
  268. return `${prefix}${(template + escape.charCodeAt(0).toString(radix)).slice(-template.length)}`;
  269. })}`;
  270. }
  271. }