Browse Source

:sparkles: text only mode

LI JIAHAO 6 years ago
parent
commit
7100b83cf9
8 changed files with 91 additions and 61 deletions
  1. 1 4
      README.md
  2. 1 0
      config.example.json
  3. 2 1
      dist/main.js
  4. 3 2
      dist/twitter.js
  5. 39 26
      dist/webshot.js
  6. 2 1
      src/main.ts
  7. 5 2
      src/twitter.ts
  8. 38 25
      src/webshot.ts

+ 1 - 4
README.md

@@ -17,10 +17,6 @@ npm i -g cqhttp-twitter-bot
 它们是什么?  
 它们是什么?  
 观察它们的文档:[https://cqhttp.cc/](https://cqhttp.cc/) [https://cqp.cc/t/15124](https://cqp.cc/t/15124)
 观察它们的文档:[https://cqhttp.cc/](https://cqhttp.cc/) [https://cqp.cc/t/15124](https://cqp.cc/t/15124)
 
 
-因为需要发图所以必须用 **酷Q Pro** 才行。[酷Q Pro](https://cqp.cc/t/14901) 是收费的,一个月 10 块左右。  
-为什么要发图?  
-因为 twitter 有很多种,转推、回复、带图片的、带视频的。如果直接发文字的话体验很不好,估计也没人会需要吧。
-
 ## 食用
 ## 食用
 
 
 ```bash
 ```bash
@@ -40,6 +36,7 @@ cqhttp-twitter-bot config.json
 | twitter_consumer_secret |  Twitter App consumer_secret | (必填) |
 | twitter_consumer_secret |  Twitter App consumer_secret | (必填) |
 | twitter_access_token_key | Twitter App access_token_key | (必填) |
 | twitter_access_token_key | Twitter App access_token_key | (必填) |
 | twitter_access_token_secret | Twitter App access_token_secret | (必填) |
 | twitter_access_token_secret | Twitter App access_token_secret | (必填) |
+| mode | 工作模式,0 为图文模式,1 为纯文本模式。图文模式必须使用 [酷Q Pro](https://cqp.cc/t/14901)。 | 0 |
 | work_interval | 对单个订阅两次拉取更新的最少间隔时间(秒) | 60 |
 | work_interval | 对单个订阅两次拉取更新的最少间隔时间(秒) | 60 |
 | webshot_delay | 抓取网页截图时等待网页加载的延迟时长(毫秒) | 5000 |
 | webshot_delay | 抓取网页截图时等待网页加载的延迟时长(毫秒) | 5000 |
 | lockfile | 本地保存订阅信息以便下次启动时恢复 | subscriber.lock |
 | lockfile | 本地保存订阅信息以便下次启动时恢复 | subscriber.lock |

+ 1 - 0
config.example.json

@@ -6,6 +6,7 @@
   "twitter_consumer_secret": "",
   "twitter_consumer_secret": "",
   "twitter_access_token_key": "",
   "twitter_access_token_key": "",
   "twitter_access_token_secret": "",
   "twitter_access_token_secret": "",
+  "mode": 0,
   "work_interval": 60,
   "work_interval": 60,
   "webshot_delay": 5000,
   "webshot_delay": 5000,
   "lockfile": "subscriber.lock",
   "lockfile": "subscriber.lock",

+ 2 - 1
dist/main.js

@@ -77,7 +77,7 @@ if (config.loglevel === undefined) {
 let redisConfig;
 let redisConfig;
 if (config.redis) {
 if (config.redis) {
     redisConfig = {
     redisConfig = {
-        redisHost: config.redis_host || "127.0.0.1",
+        redisHost: config.redis_host || '127.0.0.1',
         redisPort: config.redis_port || 6379,
         redisPort: config.redis_port || 6379,
         redisExpireTime: config.redis_expire_time || 43200,
         redisExpireTime: config.redis_expire_time || 43200,
     };
     };
@@ -142,6 +142,7 @@ const worker = new twitter_1.default({
     bot: qq,
     bot: qq,
     webshotDelay: config.webshot_delay,
     webshotDelay: config.webshot_delay,
     redis: redisConfig,
     redis: redisConfig,
+    mode: config.mode,
 });
 });
 worker.launch();
 worker.launch();
 qq.connect();
 qq.connect();

+ 3 - 2
dist/twitter.js

@@ -107,7 +107,7 @@ class default_1 {
                 }
                 }
                 if (lock.threads[lock.feed[lock.workon]].offset === 0)
                 if (lock.threads[lock.feed[lock.workon]].offset === 0)
                     tweets.splice(1);
                     tweets.splice(1);
-                return this.webshot(tweets, (msg, text) => {
+                return this.webshot(this.mode, tweets, (msg, text) => {
                     lock.threads[lock.feed[lock.workon]].subscribers.forEach(subscriber => {
                     lock.threads[lock.feed[lock.workon]].subscribers.forEach(subscriber => {
                         logger.info(`pushing data of thread ${lock.feed[lock.workon]} to ${JSON.stringify(subscriber)}`);
                         logger.info(`pushing data of thread ${lock.feed[lock.workon]} to ${JSON.stringify(subscriber)}`);
                         const hash = sha1(JSON.stringify(subscriber) + text);
                         const hash = sha1(JSON.stringify(subscriber) + text);
@@ -117,7 +117,7 @@ class default_1 {
                                 user_id: subscriber.chatID,
                                 user_id: subscriber.chatID,
                                 group_id: subscriber.chatID,
                                 group_id: subscriber.chatID,
                                 discuss_id: subscriber.chatID,
                                 discuss_id: subscriber.chatID,
-                                message: msg,
+                                message: this.mode === 0 ? msg : text,
                             });
                             });
                         };
                         };
                         if (this.redisClient) {
                         if (this.redisClient) {
@@ -171,6 +171,7 @@ class default_1 {
         this.bot = opt.bot;
         this.bot = opt.bot;
         this.webshotDelay = opt.webshotDelay;
         this.webshotDelay = opt.webshotDelay;
         this.redisConfig = opt.redis;
         this.redisConfig = opt.redis;
+        this.mode = opt.mode;
     }
     }
 }
 }
 exports.default = default_1;
 exports.default = default_1;

+ 39 - 26
dist/webshot.js

@@ -135,39 +135,52 @@ class Webshot extends CallableInstance {
                 onready();
                 onready();
         });
         });
     }
     }
-    webshot(tweets, callback, webshotDelay) {
+    webshot(mode, tweets, callback, webshotDelay) {
         let promise = new Promise(resolve => {
         let promise = new Promise(resolve => {
             resolve();
             resolve();
         });
         });
         tweets.forEach(twi => {
         tweets.forEach(twi => {
             let cqstr = '';
             let cqstr = '';
-            const url = `https://mobile.twitter.com/${twi.user.screen_name}/status/${twi.id_str}`;
+            if (mode === 0) {
-            promise = promise.then(() => this.renderWebshot(url, 1920, webshotDelay))
+                const url = `https://mobile.twitter.com/${twi.user.screen_name}/status/${twi.id_str}`;
-                .then(base64Webshot => {
+                promise = promise.then(() => this.renderWebshot(url, 1920, webshotDelay))
-                if (base64Webshot)
+                    .then(base64Webshot => {
-                    cqstr += `[CQ:image,file=base64://${base64Webshot}]`;
+                    if (base64Webshot)
-            });
+                        cqstr += `[CQ:image,file=base64://${base64Webshot}]`;
-            if (twi.extended_entities) {
-                twi.extended_entities.media.forEach(media => {
-                    promise = promise.then(() => this.fetchImage(media.media_url_https))
-                        .then(base64Image => {
-                        if (base64Image)
-                            cqstr += `[CQ:image,file=base64://${base64Image}]`;
-                    });
-                });
-            }
-            if (twi.entities && twi.entities.urls && twi.entities.urls.length) {
-                promise = promise.then(() => {
-                    const urls = twi.entities.urls
-                        .filter(urlObj => urlObj.indices[0] < twi.display_text_range[1])
-                        .map(urlObj => urlObj.expanded_url);
-                    if (urls.length) {
-                        cqstr += '\n';
-                        cqstr += urls.join('\n');
-                    }
                 });
                 });
+                if (twi.extended_entities) {
+                    twi.extended_entities.media.forEach(media => {
+                        promise = promise.then(() => this.fetchImage(media.media_url_https))
+                            .then(base64Image => {
+                            if (base64Image)
+                                cqstr += `[CQ:image,file=base64://${base64Image}]`;
+                        });
+                    });
+                }
+                if (twi.entities && twi.entities.urls && twi.entities.urls.length) {
+                    promise = promise.then(() => {
+                        const urls = twi.entities.urls
+                            .filter(urlObj => urlObj.indices[0] < twi.display_text_range[1])
+                            .map(urlObj => urlObj.expanded_url);
+                        if (urls.length) {
+                            cqstr += '\n';
+                            cqstr += urls.join('\n');
+                        }
+                    });
+                }
             }
             }
-            promise.then(() => callback(cqstr, (twi.retweeted_status || twi).full_text));
+            promise.then(() => {
+                let text = (twi.retweeted_status || twi).full_text;
+                if (twi.entities && twi.entities.urls && twi.entities.urls.length) {
+                    twi.entities.urls.forEach(url => {
+                        text = text.replace(new RegExp(url.url, 'gm'), url.expanded_url);
+                    });
+                }
+                text = text.replace(/&/gm, '&amp;')
+                    .replace(/\[/gm, '&#91;')
+                    .replace(/\]/gm, '&#93;');
+                callback(cqstr, text);
+            });
         });
         });
         return promise;
         return promise;
     }
     }

+ 2 - 1
src/main.ts

@@ -83,7 +83,7 @@ if (config.loglevel === undefined) {
 let redisConfig: IRedisConfig;
 let redisConfig: IRedisConfig;
 if (config.redis) {
 if (config.redis) {
   redisConfig = {
   redisConfig = {
-    redisHost: config.redis_host || "127.0.0.1",
+    redisHost: config.redis_host || '127.0.0.1',
     redisPort: config.redis_port || 6379,
     redisPort: config.redis_port || 6379,
     redisExpireTime: config.redis_expire_time || 43200,
     redisExpireTime: config.redis_expire_time || 43200,
   };
   };
@@ -151,6 +151,7 @@ const worker = new Worker({
   bot: qq,
   bot: qq,
   webshotDelay: config.webshot_delay,
   webshotDelay: config.webshot_delay,
   redis: redisConfig,
   redis: redisConfig,
+  mode: config.mode,
 });
 });
 worker.launch();
 worker.launch();
 
 

+ 5 - 2
src/twitter.ts

@@ -20,6 +20,7 @@ interface IWorkerOption {
   access_token_key: string;
   access_token_key: string;
   access_token_secret: string;
   access_token_secret: string;
   redis: IRedisConfig;
   redis: IRedisConfig;
+  mode: number;
 }
 }
 
 
 const logger = log4js.getLogger('twitter');
 const logger = log4js.getLogger('twitter');
@@ -36,6 +37,7 @@ export default class {
   private webshot: Webshot;
   private webshot: Webshot;
   private redisConfig: IRedisConfig;
   private redisConfig: IRedisConfig;
   private redisClient: RedisClient;
   private redisClient: RedisClient;
+  private mode: number;
 
 
   constructor(opt: IWorkerOption) {
   constructor(opt: IWorkerOption) {
     this.client = new Twitter({
     this.client = new Twitter({
@@ -50,6 +52,7 @@ export default class {
     this.bot = opt.bot;
     this.bot = opt.bot;
     this.webshotDelay = opt.webshotDelay;
     this.webshotDelay = opt.webshotDelay;
     this.redisConfig = opt.redis;
     this.redisConfig = opt.redis;
+    this.mode = opt.mode;
   }
   }
 
 
   public launch = () => {
   public launch = () => {
@@ -145,7 +148,7 @@ export default class {
         return;
         return;
       }
       }
       if (lock.threads[lock.feed[lock.workon]].offset === 0) tweets.splice(1);
       if (lock.threads[lock.feed[lock.workon]].offset === 0) tweets.splice(1);
-      return (this.webshot as any)(tweets, (msg, text) => {
+      return (this.webshot as any)(this.mode, tweets, (msg, text) => {
         lock.threads[lock.feed[lock.workon]].subscribers.forEach(subscriber => {
         lock.threads[lock.feed[lock.workon]].subscribers.forEach(subscriber => {
           logger.info(`pushing data of thread ${lock.feed[lock.workon]} to ${JSON.stringify(subscriber)}`);
           logger.info(`pushing data of thread ${lock.feed[lock.workon]} to ${JSON.stringify(subscriber)}`);
           const hash = sha1(JSON.stringify(subscriber) + text);
           const hash = sha1(JSON.stringify(subscriber) + text);
@@ -155,7 +158,7 @@ export default class {
               user_id: subscriber.chatID,
               user_id: subscriber.chatID,
               group_id: subscriber.chatID,
               group_id: subscriber.chatID,
               discuss_id: subscriber.chatID,
               discuss_id: subscriber.chatID,
-              message: msg,
+              message: this.mode === 0 ? msg : text,
             });
             });
           };
           };
           if (this.redisClient) {
           if (this.redisClient) {

+ 38 - 25
src/webshot.ts

@@ -138,37 +138,50 @@ class Webshot extends CallableInstance {
       });
       });
     })
     })
 
 
-  public webshot(tweets, callback, webshotDelay: number): Promise<void> {
+  public webshot(mode, tweets, callback, webshotDelay: number): Promise<void> {
     let promise = new Promise<void>(resolve => {
     let promise = new Promise<void>(resolve => {
       resolve();
       resolve();
     });
     });
     tweets.forEach(twi => {
     tweets.forEach(twi => {
       let cqstr = '';
       let cqstr = '';
-      const url = `https://mobile.twitter.com/${twi.user.screen_name}/status/${twi.id_str}`;
+      if (mode === 0) {
-      promise = promise.then(() => this.renderWebshot(url, 1920, webshotDelay))
+        const url = `https://mobile.twitter.com/${twi.user.screen_name}/status/${twi.id_str}`;
-        .then(base64Webshot => {
+        promise = promise.then(() => this.renderWebshot(url, 1920, webshotDelay))
-          if (base64Webshot) cqstr += `[CQ:image,file=base64://${base64Webshot}]`;
+          .then(base64Webshot => {
-        });
+            if (base64Webshot) cqstr += `[CQ:image,file=base64://${base64Webshot}]`;
-      if (twi.extended_entities) {
+          });
-        twi.extended_entities.media.forEach(media => {
+        if (twi.extended_entities) {
-          promise = promise.then(() => this.fetchImage(media.media_url_https))
+          twi.extended_entities.media.forEach(media => {
-            .then(base64Image => {
+            promise = promise.then(() => this.fetchImage(media.media_url_https))
-              if (base64Image) cqstr += `[CQ:image,file=base64://${base64Image}]`;
+              .then(base64Image => {
-            });
+                if (base64Image) cqstr += `[CQ:image,file=base64://${base64Image}]`;
-        });
+              });
-      }
+          });
-      if (twi.entities && twi.entities.urls && twi.entities.urls.length) {
+        }
-        promise = promise.then(() => {
+        if (twi.entities && twi.entities.urls && twi.entities.urls.length) {
-          const urls = twi.entities.urls
+          promise = promise.then(() => {
-            .filter(urlObj => urlObj.indices[0] < twi.display_text_range[1])
+            const urls = twi.entities.urls
-            .map(urlObj => urlObj.expanded_url);
+              .filter(urlObj => urlObj.indices[0] < twi.display_text_range[1])
-          if (urls.length) {
+              .map(urlObj => urlObj.expanded_url);
-            cqstr += '\n';
+            if (urls.length) {
-            cqstr += urls.join('\n');
+              cqstr += '\n';
-          }
+              cqstr += urls.join('\n');
-        });
+            }
+          });
+        }
       }
       }
-      promise.then(() => callback(cqstr, (twi.retweeted_status || twi).full_text));
+      promise.then(() => {
+        let text = (twi.retweeted_status || twi).full_text;
+        if (twi.entities && twi.entities.urls && twi.entities.urls.length) {
+          twi.entities.urls.forEach(url => {
+            text = text.replace(new RegExp(url.url, 'gm'), url.expanded_url);
+          });
+        }
+        text = text.replace(/&/gm, '&amp;')
+          .replace(/\[/gm, '&#91;')
+          .replace(/\]/gm, '&#93;');
+        callback(cqstr, text);
+      });
     });
     });
     return promise;
     return promise;
   }
   }