announcements.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. "use strict";
  2. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  3. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  4. return new (P || (P = Promise))(function (resolve, reject) {
  5. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  6. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  7. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  8. step((generator = generator.apply(thisArg, _arguments || [])).next());
  9. });
  10. };
  11. var __generator = (this && this.__generator) || function (thisArg, body) {
  12. var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  13. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  14. function verb(n) { return function (v) { return step([n, v]); }; }
  15. function step(op) {
  16. if (f) throw new TypeError("Generator is already executing.");
  17. while (_) try {
  18. if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  19. if (y = 0, t) op = [op[0] & 2, t.value];
  20. switch (op[0]) {
  21. case 0: case 1: t = op; break;
  22. case 4: _.label++; return { value: op[1], done: false };
  23. case 5: _.label++; y = op[1]; op = [0]; continue;
  24. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  25. default:
  26. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  27. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  28. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  29. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  30. if (t[2]) _.ops.pop();
  31. _.trys.pop(); continue;
  32. }
  33. op = body.call(thisArg, _);
  34. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  35. if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  36. }
  37. };
  38. exports.__esModule = true;
  39. exports.closeOpening = exports.newOpening = exports.provider = exports.formatProposalMessage = exports.heartbeat = exports.threads = exports.posts = exports.categories = exports.channels = void 0;
  40. var util_1 = require("./util");
  41. var getters_1 = require("./getters");
  42. var domain = require("../../config").domain;
  43. var sleep = function (ms) { return new Promise(function (resolve) { return setTimeout(resolve, ms); }); };
  44. // query API repeatedly to ensure a result
  45. var query = function (test, cb) { return __awaiter(void 0, void 0, void 0, function () {
  46. var result, i;
  47. return __generator(this, function (_a) {
  48. switch (_a.label) {
  49. case 0: return [4 /*yield*/, cb()];
  50. case 1:
  51. result = _a.sent();
  52. i = 0;
  53. _a.label = 2;
  54. case 2:
  55. if (!(i < 10)) return [3 /*break*/, 6];
  56. if (result[test] !== "")
  57. return [2 /*return*/, result];
  58. return [4 /*yield*/, cb()];
  59. case 3:
  60. result = _a.sent();
  61. return [4 /*yield*/, sleep(5000)];
  62. case 4:
  63. _a.sent();
  64. _a.label = 5;
  65. case 5:
  66. i++;
  67. return [3 /*break*/, 2];
  68. case 6: return [2 /*return*/];
  69. }
  70. });
  71. }); };
  72. // announce latest channels
  73. exports.channels = function (api, channels, sendMessage) { return __awaiter(void 0, void 0, void 0, function () {
  74. var last, current, messages, _loop_1, id;
  75. return __generator(this, function (_a) {
  76. switch (_a.label) {
  77. case 0:
  78. last = channels[0], current = channels[1];
  79. messages = [];
  80. _loop_1 = function (id) {
  81. var channel, member, _a;
  82. return __generator(this, function (_b) {
  83. switch (_b.label) {
  84. case 0: return [4 /*yield*/, query("title", function () {
  85. return api.query.contentWorkingGroup.channelById(id);
  86. })];
  87. case 1:
  88. channel = _b.sent();
  89. member = { id: channel.owner, handle: "", url: "" };
  90. _a = member;
  91. return [4 /*yield*/, getters_1.memberHandle(api, member.id.toJSON())];
  92. case 2:
  93. _a.handle = _b.sent();
  94. member.url = domain + "/#/members/" + member.handle;
  95. messages.push("<b>Channel <a href=\"" + domain + "/#//media/channels/" + id + "\">" + channel.title + "</a> by <a href=\"" + member.url + "\">" + member.handle + " (" + member.id + ")</a></b>");
  96. return [2 /*return*/];
  97. }
  98. });
  99. };
  100. id = +last + 1;
  101. _a.label = 1;
  102. case 1:
  103. if (!(id <= current)) return [3 /*break*/, 4];
  104. return [5 /*yield**/, _loop_1(id)];
  105. case 2:
  106. _a.sent();
  107. _a.label = 3;
  108. case 3:
  109. id++;
  110. return [3 /*break*/, 1];
  111. case 4:
  112. sendMessage(messages.join("\r\n\r\n"));
  113. return [2 /*return*/, current];
  114. }
  115. });
  116. }); };
  117. // forum
  118. // announce latest categories
  119. exports.categories = function (api, category, sendMessage) { return __awaiter(void 0, void 0, void 0, function () {
  120. var messages, _loop_2, id;
  121. return __generator(this, function (_a) {
  122. switch (_a.label) {
  123. case 0:
  124. messages = [];
  125. _loop_2 = function (id) {
  126. var cat, msg;
  127. return __generator(this, function (_a) {
  128. switch (_a.label) {
  129. case 0: return [4 /*yield*/, query("title", function () { return getters_1.categoryById(api, id); })];
  130. case 1:
  131. cat = _a.sent();
  132. msg = "Category " + id + ": <b><a href=\"" + domain + "/#/forum/categories/" + id + "\">" + cat.title + "</a></b>";
  133. messages.push(msg);
  134. return [2 /*return*/];
  135. }
  136. });
  137. };
  138. id = +category[0] + 1;
  139. _a.label = 1;
  140. case 1:
  141. if (!(id <= category[1])) return [3 /*break*/, 4];
  142. return [5 /*yield**/, _loop_2(id)];
  143. case 2:
  144. _a.sent();
  145. _a.label = 3;
  146. case 3:
  147. id++;
  148. return [3 /*break*/, 1];
  149. case 4:
  150. sendMessage(messages.join("\r\n\r\n"));
  151. return [2 /*return*/, category[1]];
  152. }
  153. });
  154. }); };
  155. // announce latest posts
  156. exports.posts = function (api, posts, sendMessage) { return __awaiter(void 0, void 0, void 0, function () {
  157. var last, current, messages, _loop_3, id;
  158. return __generator(this, function (_a) {
  159. switch (_a.label) {
  160. case 0:
  161. last = posts[0], current = posts[1];
  162. messages = [];
  163. _loop_3 = function (id) {
  164. var post, replyId, message, excerpt, threadId, thread, threadTitle, category, handle, msg;
  165. return __generator(this, function (_a) {
  166. switch (_a.label) {
  167. case 0: return [4 /*yield*/, query("current_text", function () {
  168. return api.query.forum.postById(id);
  169. })];
  170. case 1:
  171. post = _a.sent();
  172. replyId = +post.nr_in_thread;
  173. message = post.current_text;
  174. excerpt = message.substring(0, 100);
  175. threadId = +post.thread_id;
  176. return [4 /*yield*/, query("title", function () {
  177. return api.query.forum.threadById(threadId);
  178. })];
  179. case 2:
  180. thread = _a.sent();
  181. threadTitle = thread.title;
  182. return [4 /*yield*/, query("title", function () {
  183. return getters_1.categoryById(api, +thread.category_id);
  184. })];
  185. case 3:
  186. category = _a.sent();
  187. return [4 /*yield*/, getters_1.memberHandleByAccount(api, post.author_id.toJSON())];
  188. case 4:
  189. handle = _a.sent();
  190. msg = "<b><a href=\"" + domain + "/#/members/" + handle + "\">" + handle + "</a> posted <a href=\"" + domain + "/#/forum/threads/" + threadId + "?replyIdx=" + replyId + "\">" + threadTitle + "</a> in <a href=\"" + domain + "/#/forum/categories/" + category.id + "\">" + category.title + "</a>:</b>\n\r<i>" + excerpt + "</i> <a href=\"" + domain + "/#/forum/threads/" + threadId + "?replyIdx=" + replyId + "\">more</a>";
  191. messages.push(msg);
  192. return [2 /*return*/];
  193. }
  194. });
  195. };
  196. id = +last + 1;
  197. _a.label = 1;
  198. case 1:
  199. if (!(id <= current)) return [3 /*break*/, 4];
  200. return [5 /*yield**/, _loop_3(id)];
  201. case 2:
  202. _a.sent();
  203. _a.label = 3;
  204. case 3:
  205. id++;
  206. return [3 /*break*/, 1];
  207. case 4:
  208. sendMessage(messages.join("\r\n\r\n"));
  209. return [2 /*return*/, current];
  210. }
  211. });
  212. }); };
  213. // announce latest threads
  214. exports.threads = function (api, threads, sendMessage) { return __awaiter(void 0, void 0, void 0, function () {
  215. var last, current, messages, _loop_4, id;
  216. return __generator(this, function (_a) {
  217. switch (_a.label) {
  218. case 0:
  219. last = threads[0], current = threads[1];
  220. messages = [];
  221. _loop_4 = function (id) {
  222. var thread, title, author_id, handle, category, msg;
  223. return __generator(this, function (_a) {
  224. switch (_a.label) {
  225. case 0: return [4 /*yield*/, query("title", function () {
  226. return api.query.forum.threadById(id);
  227. })];
  228. case 1:
  229. thread = _a.sent();
  230. title = thread.title, author_id = thread.author_id;
  231. return [4 /*yield*/, getters_1.memberHandleByAccount(api, author_id.toJSON())];
  232. case 2:
  233. handle = _a.sent();
  234. return [4 /*yield*/, query("title", function () {
  235. return getters_1.categoryById(api, +thread.category_id);
  236. })];
  237. case 3:
  238. category = _a.sent();
  239. msg = "Thread " + id + ": <a href=\"" + domain + "/#/forum/threads/" + id + "\">\"" + title + "\"</a> by <a href=\"" + domain + "/#/members/" + handle + "\">" + handle + "</a> in category \"<a href=\"" + domain + "/#/forum/categories/" + category.id + "\">" + category.title + "</a>\" ";
  240. messages.push(msg);
  241. return [2 /*return*/];
  242. }
  243. });
  244. };
  245. id = +last + 1;
  246. _a.label = 1;
  247. case 1:
  248. if (!(id <= current)) return [3 /*break*/, 4];
  249. return [5 /*yield**/, _loop_4(id)];
  250. case 2:
  251. _a.sent();
  252. _a.label = 3;
  253. case 3:
  254. id++;
  255. return [3 /*break*/, 1];
  256. case 4:
  257. sendMessage(messages.join("\r\n\r\n"));
  258. return [2 /*return*/, current];
  259. }
  260. });
  261. }); };
  262. // heartbeat
  263. var getAverage = function (array) {
  264. return array.reduce(function (a, b) { return a + b; }, 0) / array.length;
  265. };
  266. exports.heartbeat = function (api, summary, timePassed, accountId, sendMessage) { return __awaiter(void 0, void 0, void 0, function () {
  267. var blocks, nominators, validators, avgDuration, era, totalStake, stakers, stakerCount, avgStake;
  268. return __generator(this, function (_a) {
  269. switch (_a.label) {
  270. case 0:
  271. blocks = summary.blocks, nominators = summary.nominators, validators = summary.validators;
  272. avgDuration = blocks.reduce(function (a, b) { return a + b.duration; }, 0) / blocks.length;
  273. return [4 /*yield*/, api.query.staking.currentEra()];
  274. case 1:
  275. era = _a.sent();
  276. return [4 /*yield*/, api.query.staking.erasTotalStake(parseInt(era))];
  277. case 2:
  278. totalStake = _a.sent();
  279. return [4 /*yield*/, api.query.staking.erasStakers(parseInt(era), accountId)];
  280. case 3:
  281. stakers = _a.sent();
  282. stakerCount = stakers.others.length;
  283. avgStake = parseInt(totalStake.toString()) / stakerCount;
  284. console.log("\n Blocks produced during " + timePassed + "h in era " + era + ": " + blocks.length + "\n Average blocktime: " + Math.floor(avgDuration) / 1000 + " s\n Average stake: " + avgStake / 1000000 + " M JOY (" + stakerCount + " stakers)\n Average number of nominators: " + getAverage(nominators) + "\n Average number of validators: " + getAverage(validators));
  285. return [2 /*return*/];
  286. }
  287. });
  288. }); };
  289. exports.formatProposalMessage = function (data) {
  290. var id = data[0], title = data[1], type = data[2], stage = data[3], result = data[4], handle = data[5];
  291. return "<b>Type</b>: " + type + "\r\n<b>Proposer</b>: <a href=\"" + domain + "/#/members/" + handle + "\">" + handle + "</a>\r\n<b>Title</b>: <a href=\"" + domain + "/#/proposals/" + id + "\">" + title + "</a>\r\n<b>Stage</b>: " + stage + "\r\n<b>Result</b>: " + result;
  292. };
  293. // providers
  294. exports.provider = function (id, address, status, sendMessage) {
  295. var msg = "[" + util_1.formatTime() + "] Storage Provider " + id + " (" + address + ") is " + status;
  296. sendMessage(msg);
  297. };
  298. exports.newOpening = function (id, sendMessage) {
  299. var msg = "New opening: <b><a href=\"" + domain + "/#/working-groups/opportunities/curators/" + id + "\">Storage Provider " + id + "</a></b>";
  300. sendMessage(msg);
  301. };
  302. exports.closeOpening = function (id, handle, sendMessage) {
  303. var msg = "<a href=\"" + domain + "/#/members/" + handle + "\">" + handle + "</a> was choosen as <b><a href=\"" + domain + "/#/working-groups/opportunities/curators/" + id + "\">Storage Provider " + id + "</a></b>";
  304. sendMessage(msg);
  305. };