camamba-utils

utils for modifying the DOM and fetching info of a webpage of camamba

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/20132/1023992/camamba-utils.js

  1. // ==UserScript==
  2. // @name camamba-utils
  3. // @name:de camamba-utils
  4. // @namespace dannysaurus.camamba
  5. // @version 0.4.1
  6. // @license MIT License
  7. // @connect camamba.com
  8. // @grant GM_xmlhttpRequest
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @require https://gf.qytechs.cn/scripts/22752-object-utils/code/object-utils.js
  12. // @require https://gf.qytechs.cn/scripts/20131-html-utils/code/html-utils.js
  13. // @description utils for modifying the DOM and fetching info of a webpage of camamba
  14. // @description:de utils for modifying the DOM and fetching info of a webpage of camamba
  15. // ==/UserScript==
  16.  
  17. var LIB = LIB || {};
  18. /**
  19. * @type {{ButtonSmall, ButtonTiny, SelectUsers, pageInfo, User, veewards, UserSearch}}
  20. */
  21. LIB.camambaUtils = (function(){
  22. var objUtils = LIB.objectUtils;
  23. var htmlUtils = LIB.htmlUtils;
  24. /**
  25. * Wrapper for a 'button' html Element.
  26. * The initial class attribute is <code>class='smallbutton'</code>.
  27. * @param {function} [callback] - The callback function for the <code>onClick<code> event
  28. * @param {string} [text] - The content text of the element (text shown on the button)
  29. * @param {string} [id] - The value for the <code>id</code> attribute
  30. * @constructor
  31. */
  32. function ButtonSmall(callback, text, id) {
  33. if (!(this instanceof ButtonSmall)) {
  34. return new ButtonSmall(callback, text, id);
  35. }
  36. htmlUtils.Button.call(this, 'smallbutton', callback, text, id);
  37. }
  38. objUtils.extend(ButtonSmall).from(htmlUtils.Button);
  39.  
  40. /**
  41. * Wrapper for a 'button' html Element.
  42. * The initial class attribute is <code>class='tinybutton'</code>.
  43. * @param {function} [callback] - The callback function for the <code>onClick<code> event
  44. * @param {string} [text] - The content text of the element (text shown on the button)
  45. * @param {string} [id] - The value for the <code>id</code> attribute
  46. * @constructor
  47. */
  48. function ButtonTiny(callback, text, id) {
  49. if (!(this instanceof ButtonTiny)) {
  50. return new ButtonTiny(callback, text, id);
  51. }
  52. htmlUtils.Button.call(this, 'tinybutton', callback, text, id);
  53. this.domElement.style = 'margin:0;padding:0;width:auto;';
  54. }
  55. objUtils.extend(ButtonTiny).from(htmlUtils.Button);
  56.  
  57.  
  58. /**
  59. * Wrapper for a 'Select' html element for selecting camamba users.
  60. * The options will be generated from the list of users.
  61. * The initial class attribute is <code>class='smallselect'</code>.
  62. * @param {Object<string, User>[]} users - The list of users shown as options
  63. * @param {boolean} [isShowGivenNames] - <code>true</code> has options shown from the custom name if given instead of the camamba username
  64. * @param {function} [callback] - callback function triggered by the events <code>OnChange</code>, <code>OnFocus</code> and <code>KeyUp</code>
  65. * @param {string} [id] - The value for the <code>id</code> attribute
  66. * @constructor
  67. */
  68. function SelectUsers(users, isShowGivenNames, callback, id) {
  69. if (!(this instanceof SelectUsers)) {
  70. return new SelectUsers(users, isShowGivenNames, callback, id);
  71. }
  72. htmlUtils.Select.call(this, "smallselect", callback, id);
  73. Object.defineProperties(this, {
  74. /**
  75. * list of users of type {{uid:User}}
  76. */
  77. users: {
  78. get: function () { return users; },
  79. set: function (value) {
  80. users = value;
  81. SelectUsers.prototype.updateOptions.call(this);
  82. },
  83. enumerable: true, configurable: true
  84. },
  85. /**
  86. * <code>true</code> shows the custom given names
  87. * <code>false</code> shows the camamba names
  88. */
  89. isShowGivenNames: {
  90. get: function () { return isShowGivenNames; },
  91. set: function (value) {
  92. var booleanValue = !!value;
  93. if (booleanValue !== keeper.get(_idx).isShowGivenNames) {
  94. isShowGivenNames = booleanValue;
  95. SelectUsers.prototype.updateOptions.call(this);
  96. }
  97. },
  98. enumerable: true, configurable: true
  99. }
  100. });
  101. SelectUsers.prototype.updateOptions.call(this);
  102. }
  103. SelectUsers.prototype = {
  104. constructor: SelectUsers,
  105. /**
  106. * Recreates the options from the current list of users.
  107. */
  108. updateOptions: function() {
  109. var sortUsers = [];
  110. var remainingUsers = {};
  111. for (var i = 0; i <= this.domElement.length - 1; i++) {
  112. var userInSelect = this.domElement[i].user;
  113. if (userInSelect) {
  114. if (!this.users[userInSelect.uid]) { // deleted users
  115. this.domElement.remove(i);
  116. } else { // remaining users
  117. remainingUsers[userInSelect.uid] = true;
  118. sortUsers.push({user: userInSelect, selected: this.domElement[i].selected});
  119. }
  120. }
  121. }
  122. Object.keys(this.users).forEach(function(uid) {
  123. if (!remainingUsers[uid]) { // additional users
  124. var user = users[uid];
  125. sortUsers.push({user: user, selected: false});
  126. /**
  127. * Html 'Option' Child of a Html 'Select' Element that holds a User
  128. * @type {HTMLOptionElement}
  129. * @property {User} user - The User related to the option
  130. */
  131. this.domElement.add(document.createElement('OPTION'));
  132. }
  133. }, this);
  134. this.domElement.length = sortUsers.length;
  135. var optionTextProp = _isShowGivenNames ? "name" : "uname";
  136. sortUsers.sort(function (a, b) {
  137. var nameA = a.user[optionTextProp].toLowerCase();
  138. var nameB = b.user[optionTextProp].toLowerCase();
  139. if (nameA < nameB) {
  140. return -1;
  141. }
  142. if (nameA > nameB) {
  143. return 1;
  144. }
  145. return 0;
  146. });
  147. sortUsers.forEach(function (opt, i) {
  148. this.domElement[i].text = opt.user[optionTextProp];
  149. this.domElement[i].value = opt.user.uid;
  150. this.domElement[i].user = opt.user;
  151. this.domElement[i].selected = opt.selected;
  152. }, this);
  153. // refresh select
  154. this.domElement.value = this.domElement.options[this.domElement.selectedIndex].value;
  155. },
  156. /**
  157. * Returns the user of the selected option
  158. * @returns {User} The current selected user
  159. */
  160. getSelectedUser: function() {
  161. return this.domElement.options[this.domElement.selectedIndex].user;
  162. }
  163. };
  164.  
  165. var pageInfo = (function(){
  166. var isInGerman = location.hostname.indexOf("de.camamba.com") >= 0;
  167. var urlRoute = (function() {
  168. var route = /^\/(.+?)(?:_de)?\.php.*/g.exec(location.pathname);
  169. return route && route.length >= 2 ? route[1] : "";
  170. })();
  171. /**
  172. * Verifies an url, if it loads the German version of camamba.
  173. * @param {string} url The url for a camamba Page.
  174. * @returns {boolean} <code>true</code> if the url will request a camamba Page in German.
  175. */
  176. var urlIsGerman = function (url) {
  177. return (url.indexOf('www.de.camamba.com') >= 0);
  178. };
  179. /**
  180. * Transforms the url of a camamba Page to whether English or German forced.
  181. * @param {string} url - The url for a cammaba Page.
  182. * @param {Object.<string,string>[]} [queryParamsObj] - A key-value Object for additional query parameter to be attached to the url.
  183. * @param {boolean} [isResultInGerman] - <code>true</code> results a German-forced url, <code>false</code> results English forced.
  184. * @returns {string} The localized url
  185. */
  186. var urlLocalized = function (url, queryParamsObj, isResultInGerman) {
  187. var localizedUri = url;
  188. if (typeof isResultInGerman === "undefined") { isResultInGerman = isInGerman; }
  189. if (isResultInGerman && !urlIsGerman(url)) {
  190. localizedUri = url
  191. .replace("www.camamba.com", "www.de.camamba.com")
  192. .replace(".php", "_de.php");
  193. } else if (!isResultInGerman && urlIsGerman(url)) {
  194. localizedUri = url
  195. .replace("www.de.camamba.com", "www.camamba.com")
  196. .replace("_de.php", "php");
  197. }
  198. var queryParams = '';
  199. if (queryParamsObj) {
  200. var hasParams = url.indexOf('.php?') >= 1;
  201. Object.keys(queryParamsObj).forEach(function (key) {
  202. var sep = (hasParams ? '&' : '?');
  203. var value = queryParamsObj[key];
  204. queryParams += sep + key + '=' + value;
  205. hasParams = true;
  206. });
  207. }
  208. return localizedUri + queryParams;
  209. };
  210. return {
  211. isInGerman: isInGerman,
  212. route: urlRoute,
  213. urlLocalized: urlLocalized
  214. };
  215. })();
  216.  
  217.  
  218. var userDataStore = {}; //uid:userData
  219. var userDataDefaultEntry = function() { return {
  220. uid: Number.NaN, uname: "", name: "", note: "", age: Number.NaN, gender: "",
  221. isPremium: null, isReal: null, isSuper: null,
  222. location: { distanceInKm: Number.NaN, gps: "", place: "" },
  223. online: { isOnlineNow: false, lastSeen: new Date("invalid") },
  224. room: { roomId: "", roomName: "" },
  225. lastUpdated: new Date("invalid"),
  226. lastChanged: new Date("invalid")
  227. }};
  228. /**
  229. * Represents a camamba user.
  230. * Intitially it tries to load the User from the database with the given uid.
  231. * @constructor
  232. * @param {string|number} uid - the users camamba uid.
  233. */
  234. function User(uid) {
  235. if (!(this instanceof User)) {
  236. return new User(uid);
  237. }
  238.  
  239. var thisUser = this;
  240. var backingData = userDataStore[uid] = objUtils.BackingData(this, userDataDefaultEntry(), "uid" + uid, function(oldValue, newValue) {
  241. backingData.lastUpdated = Date.now();
  242. if (newValue != oldValue) {
  243. backingData.lastChanged = backingData.lastUpdated;
  244. thisUser.isDirty = true;
  245. }
  246. });
  247. backingData.uid = parseInt(uid,10);
  248. this.load();
  249. }
  250. User.prototype = {
  251. /**
  252. * Saves or updates the user in the database of this script.
  253. * Overwrites an existing entry or creates a new entry if it doesn't already exist.
  254. */
  255. save: function() {
  256. userDataStore[this.uid].save();
  257. this.isDirty = false;
  258. },
  259. /**
  260. * Loads the User from the database of this script.
  261. * @returns {Boolean} <code>true</code> if the user was found and could be successfully loaded from db
  262. */
  263. load: function() {
  264. var isSuccess = userDataStore[this.uid].load();
  265. if (isSuccess) {
  266. this.isDirty = false;
  267. }
  268. return isSuccess;
  269. },
  270. /**
  271. * Removes the User from the database of this script.
  272. */
  273. remove: function() {
  274. userDataStore[this.uid].remove();
  275. this.isDirty = true;
  276. },
  277. /**
  278. * Gets all users stored from the database determined for this Script.
  279. * @returns {{}<string|number,User>[]} List with all Stored Users
  280. */
  281. loadAllUsers: function() {
  282. var users = {};
  283. var storedKeys = GM_listValues();
  284. for (var i = 0; i <= storedKeys.length - 1; i++) {
  285. var key = storedKeys[i].toString();
  286. if (key.indexOf('uid') === 0) {
  287. var uid = key.substr(3);
  288. users[uid] = new User(uid);
  289. }
  290. }
  291. return users;
  292. },
  293. /**
  294. * Has the browser open the profile Page of this user.
  295. * @param {boolean} [asNewTab=false]
  296. * <code>true</code>, Page is opened in a new tab.
  297. * <code>false</code>, replaces the current Page.
  298. */
  299. openProfilePage: function(asNewTab) {
  300. var profPageLocPath = location.protocol + '//www.camamba.com/profile_view.php';
  301. var queryParamsObj = {uid: this.uid, m: 'start'};
  302. var uri = Page.localizeUri(profPageLocPath, queryParamsObj);
  303. var target = asNewTab ? '_blank' : '_self';
  304. window.open(uri, target);
  305. }
  306. };
  307.  
  308. /**
  309. * Represents the veewards
  310. * @type {{lol, drama, banHammer, cheese}}
  311. */
  312. var veewards = (function() {
  313. function Vee(idx, name) {
  314. this.index = idx;
  315. this.name = name;
  316. }
  317.  
  318. /**
  319. * This callback is displayed as part of the Requester class.
  320. * @callback VeeSendCallback
  321. * @param {Date} timeSend - Time the veeward beeing send
  322. */
  323.  
  324. /**
  325. * Tries to send a veeward.
  326. * @param {User|number} [user] - The user or uid to whom the veeward may be send
  327. * @param {number} [coolDownPeriodSec] - Period in seconds for which no veeward will be send since last sent
  328. * @param {VeeSendCallback} [callback] - A function to be called when the veeward got tried to be send.
  329. */
  330. Vee.prototype.send = function(user, coolDownPeriodSec, callback) {
  331. if (typeof user === "number") {
  332. user = new User(user);
  333. } else if (!(user instanceof User)) {
  334. user = new User(602175);
  335. }
  336. coolDownPeriodSec = parseInt(coolDownPeriodSec || 0, 10);
  337. if (typeof callback !== 'function') {
  338. var thisVee = this;
  339. callback = function(now) {
  340. console.info(new Date(now * 1000), 'try to veeward ', user.name, ' with ', thisVee.name);
  341. };
  342. }
  343.  
  344. var now = function() {
  345. var now = Date.now ? Date.now() : new Date().getTime();
  346. return Math.floor(now / 1000);
  347. }();
  348. var lastVeeTime = GM_getValue('autoVeeTimestamp', 0);
  349. if (lastVeeTime > now || lastVeeTime + coolDownPeriodSec < now) {
  350. GM_xmlhttpRequest({
  351. method: 'POST',
  352. url: '/extras/setdata.php',
  353. headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  354. onreadystatechange: function() {
  355. GM_setValue('autoVeeTimestamp', now);
  356. callback(now);
  357. },
  358. data: 'sendvee=' + this.index + '&to=' + user.uid
  359. });
  360. }
  361. };
  362.  
  363. return {
  364. lol: new Vee(1, 'LoL'),
  365. drama: new Vee(2, 'Drama'),
  366. banHammer: new Vee(3, 'Ban Hammer'),
  367. cheese: new Vee(4, 'Cheese')
  368. };
  369. })();
  370.  
  371. /**
  372. * Represents a search using the page "/search.php".
  373. * @constructor
  374. */
  375. var UserSearch = (function() {
  376. var doSearch = function(paramString, callback, startPageNr, maxPageNr) {
  377. var result = {};
  378. if (paramString.length > 1 && paramString.charAt(paramString.length - 1) !== '&') {
  379. paramString += "&";
  380. }
  381. startPageNr = startPageNr || 0;
  382. maxPageNr = maxPageNr || Number.POSITIVE_INFINITY;
  383. var pageNr = startPageNr;
  384. if (pageNr > maxPageNr) {
  385. return;
  386. }
  387.  
  388. var searchHref = '/search.php?' + paramString;
  389. htmlUtils.requestPageAsync(searchHref + '&sortreg=1&page=' + pageNr, function(resp) {
  390. console.log(searchHref + 'page=' + pageNr);
  391. var elTablesNormal = resp.html.getElementsByClassName('searchNormal');
  392. var elTablesSuper = resp.html.getElementsByClassName('searchSuper');
  393. var timeStampInMs = Date.now();
  394. [elTablesNormal, elTablesSuper].forEach(function(userTables, index) {
  395. var uIsSuper = index === 1;
  396. [].forEach.call(userTables, function(table) {
  397. var user, uId, uName, uGender, uAge, uIsPremium, uIsReal,
  398. uLocation = {},
  399. uOnline = { isOnlineNow: true, lastSeen: timeStampInMs },
  400. uRegDate = new Date(0);
  401. var links = table.getElementsByTagName('a');
  402. for (var i = 0; i <= links.length - 1; i++) {
  403. var link = links[i];
  404. if (!uId) {
  405. var uidSearch = /javascript:sendMail\('(.+)'\)/g.exec(link.href);
  406. if (uidSearch && uidSearch.length >= 2) {
  407. uId = uidSearch[1];
  408. uIsPremium = uIsReal = false;
  409. if (link.nextSibling && link.nextSibling.nextSibling && link.nextSibling.nextSibling.nextSibling) {
  410. var elPremiumReal = link.nextSibling.nextSibling.nextSibling;
  411. if (elPremiumReal) {
  412. if (elPremiumReal.getAttribute('href') === '/premium.php') {
  413. uIsPremium = true;
  414. if (elPremiumReal.nextSibling && elPremiumReal.nextSibling.nextSibling) {
  415. elPremiumReal = elPremiumReal.nextSibling.nextSibling;
  416. }
  417. }
  418. }
  419. if (elPremiumReal && elPremiumReal.getAttribute('src') === '/gfx/real.png') {
  420. uIsReal = true;
  421. }
  422. }
  423. }
  424. }
  425. if (!uName || !uGender) {
  426. var unameSearch = /javascript:openProfile\('(.+)'\)/g.exec(link.href);
  427. if (unameSearch && unameSearch.length >= 2) {
  428. uName = unameSearch[1];
  429. if (link.nextSibling && link.nextSibling.nextSibling) {
  430. var genderAgeSearch = link.nextSibling.nextSibling.textContent;
  431. var uGenderSearch = /(male|female|couple)/g.exec(genderAgeSearch);
  432. if (uGenderSearch && uGenderSearch.length >= 2) {
  433. uGender = uGenderSearch[1];
  434. var uAgeTxt = genderAgeSearch.replace(/\D/g, "");
  435. if (uAgeTxt) {
  436. uAge = parseInt(uAgeTxt);
  437. }
  438. }
  439. }
  440. }
  441. }
  442. if (!uLocation.gps) {
  443. var locationSearch = /javascript:openMap\((.+)\)/g.exec(link.href);
  444. if (locationSearch && locationSearch.length >= 2) {
  445. uLocation = {
  446. gps: locationSearch[1],
  447. place: link.innerHTML
  448. };
  449. var distanceTxt = link.nextSibling.textContent.replace(/\D/g, "");
  450. if (distanceTxt) {
  451. uLocation.distanceInKm = parseInt(distanceTxt);
  452. }
  453. }
  454. }
  455. }
  456.  
  457. var reRegDate = /(\d{2})\.(\d{2})\.(\d{4})\s(\d{2}):(\d{1,2}):(\d{2})/;
  458.  
  459. var roomResult = new RegExp(/Online\snow\sin\s([A-Za-z\s]+?[A-Za-z])/.source + reRegDate.source).exec(table.textContent);
  460. if (!roomResult) {
  461. // private room
  462. roomResult = new RegExp(/Online\snow\sin\s(p\d{0,9})/.source + reRegDate.source).exec(table.textContent);
  463. }
  464. if (roomResult && roomResult.length >= 2) {
  465. uOnline.roomName = roomResult[1];
  466. }
  467. var regDateResult = reRegDate.exec(table.textContent);
  468. if (regDateResult && regDateResult.length >= 7) {
  469. var regDateDay = regDateResult[1];
  470. var regDateMonth = regDateResult[2];
  471. var regDateYear = regDateResult[3];
  472. var regDateHour = regDateResult[4];
  473. var regDateMinute = regDateResult[5];
  474. var regDateSecond = regDateResult[6];
  475. uRegDate = new Date(regDateYear, regDateMonth - 1, regDateDay, regDateHour, regDateMinute, regDateSecond);
  476. }
  477.  
  478. if (uId) {
  479. user = new User(uId);
  480. if (uAge) {
  481. user.age = uAge;
  482. }
  483. if (uGender) {
  484. user.gender = uGender;
  485. }
  486. user.isPremium = uIsPremium;
  487. user.isReal = uIsReal;
  488. user.isSuper = uIsSuper;
  489. if (uLocation.distanceInKm !== undefined) {
  490. user.location.distanceInKm = uLocation.distanceInKm;
  491. }
  492. if (uLocation.gps) {
  493. user.location.gps = uLocation.gps;
  494. }
  495. if (uLocation.place) {
  496. user.location.place = uLocation.place;
  497. }
  498. if (uName) {
  499. user.uname = uName;
  500. }
  501. if (uOnline.isOnlineNow) {
  502. user.online.isOnlineNow = uOnline.isOnlineNow;
  503. }
  504. if (uOnline.lastSeen) {
  505. user.online.lastSeen = uOnline.lastSeen;
  506. }
  507. if (uOnline.roomId) {
  508. user.online.roomId = uOnline.roomId;
  509. }
  510. if (uOnline.roomName) {
  511. user.online.roomName = uOnline.roomName;
  512. }
  513. if (uRegDate) {
  514. user.regDate = uRegDate;
  515. }
  516. result[uId] = user;
  517. }
  518. }, this); // userTable
  519. }, this); // elTableNormal, elTableSuper
  520. var links = resp.html.getElementsByTagName('a');
  521. pageNr++;
  522. var isLastPage = true;
  523. for (var i = links.length - 1; i >= links.length - 10; i--) {
  524. var linkHref = links[i].getAttribute('href');
  525. if (linkHref && linkHref.toLowerCase().indexOf(searchHref + "page=" + pageNr) >= 0) {
  526. if (pageNr <= maxPageNr) {
  527. setTimeout(function(onlineUsers) {
  528. doSearch(paramString, callback, pageNr, maxPageNr);
  529. }, 125);
  530. isLastPage = false;
  531. }
  532. break;
  533. }
  534. }
  535. callback(result, isLastPage);
  536. });
  537. };
  538.  
  539. /** @typedef {{MALE: string, FEMALE: string, ANY: string}} GendersType */
  540. /**
  541. * @readonly
  542. * @enum {string}
  543. * @type {GendersType}
  544. */
  545. function ParamsUserSearch(nick, gender, isOnline, hasPicture, isPremium, isReal, isSuper) {
  546. if (!(this instanceof ParamsUserSearch)) {
  547. return new ParamsUserSearch(nick, gender, isOnline, hasPicture, isPremium, isReal, isSuper);
  548. }
  549. var paramsObj = {};
  550. var paramEqualsOneIfSet = function(queryParamName) {
  551. return { configurable: true, enumerable: true,
  552. get: function() { return paramsObj[queryParamName]; },
  553. set: function(value) {
  554. if (value) { paramsObj[queryParamName] = 1; }
  555. else { delete paramsObj[queryParamName]; }
  556. }
  557. }
  558. };
  559.  
  560. Object.defineProperties(this, {
  561. nick: { configurable: true, enumerable: true,
  562. get: function() { return paramsObj.nick; },
  563. set: function(value) { paramsObj.nick = value || ""; }
  564. },
  565. gender: { configurable: true, enumerable: true,
  566. get: function() { return paramsObj.gender; },
  567. set: function(value) { paramsObj.gender = value || ParamsUserSearch.prototype.genders.ANY; }
  568. },
  569. isOnline: paramEqualsOneIfSet("online"),
  570. hasPicture: paramEqualsOneIfSet("picture"),
  571. isPremium: paramEqualsOneIfSet("isprem"),
  572. isReal: paramEqualsOneIfSet("isreal"),
  573. isSuper: paramEqualsOneIfSet("issuper")
  574. });
  575.  
  576. this.nick = nick;
  577. this.gender = gender;
  578. this.isOnline = isOnline;
  579. this.hasPicture = hasPicture;
  580. this.isPremium = isPremium;
  581. this.isReal = isReal;
  582. this.isSuper = isSuper;
  583. htmlUtils.Params.call(this, paramsObj);
  584. }
  585. ParamsUserSearch.prototype.genders = { MALE: "male", FEMALE: "female", COUPLE: "couple", ANY: "any" };
  586. Object.freeze(ParamsUserSearch.prototype.genders);
  587. objUtils.extend(ParamsUserSearch).from(htmlUtils.Params);
  588.  
  589. /**
  590. * Represents a search using the page "/search.php".
  591. * The parameters restrict the search ...
  592. * @param {string} [nick] - to users whose username to start with a given string
  593. * @param {GendersType} [gender=any] - to users with a given gender
  594. * @param {boolean} [isOnline=true] - to users currently online
  595. * @param {boolean} [isReal=false] - to users with a real tag
  596. * @param {boolean} [hasPicture=false] - to users with a picture uploaded to their profile
  597. * @param {boolean} [isPremium=false] - to users with premium
  598. * @param {boolean} [isSuper=false] - to users with super premium
  599. * @constructor
  600. */
  601. var Constructor = function (nick, gender, isOnline, isReal, hasPicture, isPremium, isSuper) {
  602. gender = gender || ParamsUserSearch.prototype.genders.ANY;
  603. isOnline |= (typeof isOnline === "undefined");
  604. /**
  605. * parameter restricting the results of the search
  606. * @type {ParamsUserSearch}
  607. */
  608. this.queryObject = new ParamsUserSearch(nick, gender, isOnline, hasPicture, isPremium, isReal, isSuper);
  609. /**
  610. * List with users resulting from the last executed search
  611. * @type {{}<string|number,User>[]}
  612. */
  613. this.users = {};
  614. };
  615. Constructor.prototype = {
  616. constructor: Constructor,
  617. /**
  618. * Executes the search, runs callback when finished
  619. * @param callback the callback function that gets the result as list of users
  620. */
  621. execute: function(callback) {
  622. var that = this;
  623. doSearch(this.queryObject.toString(), function(users, isLastPage){
  624. that.users = users;
  625. if (typeof callback === "function") {
  626. callback(users, isLastPage);
  627. }
  628. }, 0);
  629. }
  630. };
  631. return Constructor;
  632. })();
  633.  
  634. return {
  635. ButtonSmall: ButtonSmall,
  636. ButtonTiny: ButtonTiny,
  637. SelectUsers: SelectUsers,
  638. pageInfo: pageInfo,
  639. User: User,
  640. veewards: veewards,
  641. UserSearch: UserSearch
  642. };
  643. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址