Browse Source

fix +/- operations on unsafe integers w/o bigint

Mike L 4 years ago
parent
commit
f52e1026be
4 changed files with 44 additions and 6 deletions
  1. 1 1
      dist/command.js
  2. 21 2
      dist/twitter.js
  3. 2 2
      src/command.ts
  4. 20 1
      src/twitter.ts

+ 1 - 1
dist/command.js

@@ -53,7 +53,7 @@ https://twitter.com/TomoyoKurosawa/status/1294613494860361729`);
     if (match[1]) {
         const matchStatus = match[1].match(/\/status\/(\d+)/);
         if (matchStatus) {
-            offset = String(matchStatus[1] - 1);
+            offset = twitter_1.bigNumPlus(matchStatus[1], '-1');
             delete match[1];
         }
     }

+ 21 - 2
dist/twitter.js

@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
     });
 };
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.sendTweet = exports.ScreenNameNormalizer = void 0;
+exports.sendTweet = exports.bigNumPlus = exports.ScreenNameNormalizer = void 0;
 const fs = require("fs");
 const path = require("path");
 const Twitter = require("twitter");
@@ -34,6 +34,22 @@ class ScreenNameNormalizer {
 }
 exports.ScreenNameNormalizer = ScreenNameNormalizer;
 ScreenNameNormalizer.normalize = (username) => username.toLowerCase().replace(/^@/, '');
+exports.bigNumPlus = (num1, num2) => {
+    const split = (num) => num.replace(/^(-?)(\d+)(\d{15})$/, '$1$2,$1$3')
+        .replace(/^([^,]*)$/, '0,$1').split(',')
+        .map(Number);
+    let [high, low] = [split(num1), split(num2)].reduce((a, b) => [a[0] + b[0], a[1] + b[1]]);
+    const [highSign, lowSign] = [high, low].map(Math.sign);
+    if (highSign === 0)
+        return low.toString();
+    if (highSign !== lowSign) {
+        [high, low] = [high - highSign, low - lowSign * Math.pow(10, 15)];
+    }
+    else {
+        [high, low] = [high + ~~(low / Math.pow(10, 15)), low % Math.pow(10, 15)];
+    }
+    return `${high}${Math.abs(low).toString().padStart(15, '0')}`;
+};
 exports.sendTweet = (id, receiver) => {
     throw Error();
 };
@@ -94,7 +110,10 @@ class default_1 {
                 tweet_mode: 'extended',
             };
             return this.client.get(endpoint, config)
-                .then((tweet) => this.workOnTweets([tweet], sender));
+                .then((tweet) => {
+                logger.debug(`api returned tweet ${JSON.stringify(tweet)} for query id=${id}`);
+                return this.workOnTweets([tweet], sender);
+            });
         };
         this.sendTweets = (source, ...to) => (msg, text, author) => {
             to.forEach(subscriber => {

+ 2 - 2
src/command.ts

@@ -3,7 +3,7 @@ import * as path from 'path';
 
 import { relativeDate } from './datetime';
 import { getLogger } from './loggers';
-import { sendTweet, ScreenNameNormalizer as normalizer } from './twitter';
+import { bigNumPlus, sendTweet, ScreenNameNormalizer as normalizer } from './twitter';
 
 const logger = getLogger('command');
 
@@ -58,7 +58,7 @@ https://twitter.com/TomoyoKurosawa/status/1294613494860361729`);
   if (match[1]) {
     const matchStatus = match[1].match(/\/status\/(\d+)/);
     if (matchStatus) {
-      offset = String(matchStatus[1] as unknown as number - 1);
+      offset = bigNumPlus(matchStatus[1], '-1');
       delete match[1];
     }
   }

+ 20 - 1
src/twitter.ts

@@ -42,6 +42,22 @@ export class ScreenNameNormalizer {
   }
 }
 
+export const bigNumPlus = (num1: string, num2: string) => {
+  const split = (num: string) =>
+    num.replace(/^(-?)(\d+)(\d{15})$/, '$1$2,$1$3')
+    .replace(/^([^,]*)$/, '0,$1').split(',')
+    .map(Number);
+  let [high, low] = [split(num1), split(num2)].reduce((a, b) => [a[0] + b[0], a[1] + b[1]]);
+  const [highSign, lowSign] = [high, low].map(Math.sign);
+  if (highSign === 0) return low.toString();
+  if (highSign !== lowSign) {
+    [high, low] = [high - highSign, low - lowSign * 10 ** 15];
+  } else {
+    [high, low] = [high + ~~(low / 10 ** 15), low % 10 ** 15];
+  }
+  return `${high}${Math.abs(low).toString().padStart(15, '0')}`;
+};
+
 export let sendTweet = (id: string, receiver: IChat): void => {
   throw Error();
 };
@@ -172,7 +188,10 @@ export default class {
       tweet_mode: 'extended',
     };
     return this.client.get(endpoint, config)
-    .then((tweet: Tweet) => this.workOnTweets([tweet], sender));
+    .then((tweet: Tweet) => {
+      logger.debug(`api returned tweet ${JSON.stringify(tweet)} for query id=${id}`);
+      return this.workOnTweets([tweet], sender);
+    });
   }
 
   private sendTweets = (source?: string, ...to: IChat[]) =>