Add files via upload

This commit is contained in:
liberliber 2019-08-21 15:27:23 +07:00 committed by GitHub
parent 6ebfb93361
commit c4b675f45a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 631 additions and 0 deletions

467
src/api.js Normal file
View file

@ -0,0 +1,467 @@
const thrift = require('thrift-http');
const unirest = require('unirest');
const qrcode = require('qrcode-terminal');
const util = require("util");
const mime = require("mime");
const fs = require('fs');
const path = require('path');
const rp = require('request-promise');
const request = require('request');
const LineService = require('../curve-thrift/LineService');
const {
LoginResultType,
IdentityProvider,
ContentType,
Message,
LoginRequest
} = require('../curve-thrift/line_types');
const PinVerifier = require('./pinVerifier');
var config = require('./config');
var moment = require('moment');
var reqx = new LoginRequest();
var reqxy = new LoginRequest();
class LineAPI {
constructor() {
this.config = config;
this.setTHttpClient();
this.axz = false;
this.axy = false;
this.gdLine = "http://gd2.line.naver.jp";
this.gdLine2 = "http://gf.line.naver.jp";
}
setTHttpClient(options = {
protocol: thrift.TCompactProtocol,
transport: thrift.TBufferedTransport,
headers: this.config.Headers,
path: this.config.LINE_HTTP_URL,
https: true
}) {
//options.headers['X-Line-Application'] = 'CHROMEOS\t2.1.0\tChrome_OS\t1';
options.headers['X-Line-Application'] = 'IOSIPAD 7.14.0 iPhone OS 10.12.0';
//options.headers['X-Line-Application'] = 'DESKTOPMAC\t5.3.3-YOSEMITE-x64\tMAC\t10.12.0';
this.options = options;
this.connection =
thrift.createHttpConnection(this.config.LINE_DOMAIN_3RD, 443, this.options);
this.connection.on('error', (err) => {
console.log('err',err);
return err;
});
if(this.axz === true){
this._channel = thrift.createHttpClient(require('../curve-thrift/ChannelService.js'), this.connection);this.axz = false;
} else if(this.axy === true){
this._authService = thrift.createHttpClient(require('../curve-thrift/AuthService.js'), this.connection);this.axy = false;
} else {
this._client = thrift.createHttpClient(LineService, this.connection);
}
}
async _chanConn(){
this.options.headers['X-Line-Access'] = this.config.tokenn;
this.options.path = this.config.LINE_CHANNEL_PATH;
this.axz = true;
this.setTHttpClient(this.options);
return Promise.resolve();
}
async _authConn(){
this.axy = true;
this.options.path = this.config.LINE_RS;
this.setTHttpClient(this.options);
return Promise.resolve();
}
async _tokenLogin(authToken, certificate) {
this.options.path = this.config.LINE_COMMAND_PATH;
this.config.Headers['X-Line-Access'] = authToken;config.tokenn = authToken;
this.setTHttpClient(this.options);
return Promise.resolve({ authToken, certificate });
}
_qrCodeLogin() {
this.setTHttpClient();
return new Promise((resolve, reject) => {
this._client.getAuthQrcode(true, 'N0HE4D-YOUNG',(err, result) => {
const qrcodeUrl = `line://au/q/${result.verifier}`;
qrcode.generate(qrcodeUrl,{small: true});
console.info(`\n\nlink qr code is: ${qrcodeUrl}`)
Object.assign(this.config.Headers,{ 'X-Line-Access': result.verifier });
unirest.get('https://gd2.line.naver.jp/Q')
.headers(this.config.Headers)
.timeout(120000)
.end(async (res) => {
const verifiedQr = res.body.result.verifier;
this._authConn();
reqx.type = 1;
reqx.verifier = verifiedQr;
this._authService.loginZ(reqx,(err,success) => {
config.tokenn = success.authToken;
config.certificate = success.certificate;
const authToken = config.tokenn;
const certificate = config.certificate;
this.options.headers['X-Line-Access'] = config.tokenn;
this.options.path = this.config.LINE_COMMAND_PATH;
this.setTHttpClient(this.options);
this.options.headers['User-Agent'] = 'Line/7.18.1';
this.axz = true;
this.setTHttpClient(this.options);
this.axz = false;
resolve({ authToken, certificate, verifiedQr });
})
});
});
});
}
_xlogin(id,password){
const pinVerifier = new PinVerifier(id, password);
return new Promise((resolve, reject) => (
this._setProvider(id).then(() => {
this.setTHttpClient();
this._getRSAKeyInfo(this.provider, (key, credentials) => {
this.options.path = this.config.LINE_RS;
this.setTHttpClient(this.options);
const rsaCrypto = pinVerifier.getRSACrypto(credentials);
reqx.type = 0;
reqx.identityProvider = this.provider;
reqx.identifier = rsaCrypto.keyname;
reqx.password = rsaCrypto.credentials;
reqx.keepLoggedIn = true;
reqx.accessLocation = this.config.ip;
reqx.systemName = 'Js-Kicker';
reqx.e2eeVersion = 0;
try{
this._client.loginZ(reqx,
(err,success) => {
if (err) {
console.log('\n\n');
console.error("=> "+err.reason);
process.exit();
}
this.options.path = this.config.LINE_COMMAND_PATH;
this.setTHttpClient(this.options);
this._authConn();
this._client.pinCode = success.pinCode;
console.info("\n\n=============================\nEnter This Pincode => "+success.pinCode+"\nto your mobile phone in 2 minutes\n=============================");
this._checkLoginResultType(success.type, success);
reqxy.type = 1;
this._loginWithVerifier((verifierResult) => {
this.options.path = this.config.LINE_COMMAND_PATH;
this.setTHttpClient(this.options);
config.tokenn = verifierResult.authToken;
this._checkLoginResultType(verifierResult.type, verifierResult);
resolve(verifierResult);
});
});
}catch(error) {
console.log('error');
console.log(error);
}
})
})
));
}
async _loginWithVerifier(callback) {
let retx = await this.getJson(this.config.LINE_CERTIFICATE_URL)
reqxy.verifier = retx.result.verifier;
this._authService.loginZ(reqxy,(err,success) => {
callback(success);
})
}
_setProvider(id) {
this.provider = this.config.EMAIL_REGEX.test(id) ?
IdentityProvider.LINE :
IdentityProvider.NAVER_KR;
return this.provider === IdentityProvider.LINE ?
this.getJson(this.config.LINE_SESSION_LINE_URL) :
this.getJson(this.config.LINE_SESSION_NAVER_URL);
}
async _getRSAKeyInfo(provider, callback){
let result = await this._client.getRSAKeyInfo(provider);
callback(result.keynm, result);
}
_checkLoginResultType(type, result) {
this.config.Headers['X-Line-Access'] = result.authToken || result.verifier;
if (result.type === LoginResultType.SUCCESS) {
this.certificate = result.certificate;
this.authToken = result.authToken;
} else if (result.type === LoginResultType.REQUIRE_QRCODE) {
console.log('require QR code');
} else if (result.type === LoginResultType.REQUIRE_DEVICE_CONFIRM) {
console.log('require device confirm');
} else {
throw new Error('unkown type');
}
return result;
}
async _sendMessage(message, txt ,seq = 0) {
message.text = txt;
return await this._client.sendMessage(0, message);
}
_kickMember(group,memid) {
return this._client.kickoutFromGroup(0,group,memid);
}
_cancel(groupid,member) {
return this._client.cancelGroupInvitation(0,groupid,member);
}
async _getGroupsJoined() {
return await this._client.getGroupIdsJoined()
}
async _getGroupsInvited() {
return await this._client.getGroupIdsInvited();
}
async _myProfile() {
return await this._client.getProfile();
}
_inviteIntoGroup(group,memid) {
return this._client.inviteIntoGroup(0,group,memid);
}
async _findGroupByName(name) {
let group = [];
let groupID = await this._getGroupsJoined();
let groups = await this._getGroups(groupID);
for (let key in groups) {
if(groups[key].name === name){
group.push(groups[key]);
}
}
return group;
}
async _refreshGroup() {
await this._getGroupsInvited();
await this._getGroupsJoined();
return;
}
_rejectGroupInvitation(groupIds) {
return this._client.rejectGroupInvitation(0,groupIds);
}
async _createGroup(groupName,members) {
await this._getAllContactIds();
return this._client.createGroup(0,groupName,members);
}
async _getAllContactIds(){
return await this._client.getAllContactIds();
}
async _createRoom(memberids) {
return await this._client.createRoom(0,[memberids]);
}
async _acceptGroupInvitation(groupid) {
this._client.acceptGroupInvitation(0,groupid);
await this._refreshGroup();
return;
}
_invite(group,member) {
return this._client.inviteIntoGroup(0, group, member)
}
async _updateGroup(group) {
return await this._client.updateGroup(0, group)
}
async _updateProfile(profile) {
return await this._client.updateProfile(0, profile)
}
_getContacts(mid) {
return this._client.getContacts(mid)
}
async _getGroups(groupId) {
return await this._client.getGroups(groupId);
}
async _getGroup(groupId) {
return await this._client.getGroup(groupId);
}
_leaveGroup(gid) {
return this._client.leaveGroup(0,gid);
}
async _reissueGroupTicket(groupId) {
return await this._client.reissueGroupTicket(groupId);
}
async _findGroupByTicket(ticketID){
return await this._client.findGroupByTicket(ticketID);
}
async _acceptGroupInvitationByTicket(gid,ticketID){
this._refreshGroup();
return await this._client.acceptGroupInvitationByTicket(0,gid,ticketID);
}
async _sendFileByUrl(message,uri) {
let media = 1;
if (!fs.existsSync(__dirname+'/tmp')){
await fs.mkdirSync(__dirname+'/tmp');
}
let head = await unirest.head(uri,async (res) => {
let formatFile = res.headers['content-type'].split('/')[1].toLowerCase();
let locationFile = __dirname + `/tmp/${Math.floor(Math.random() * 100)}.${formatFile}`;
await unirest.get(uri).end().pipe(fs.createWriteStream(locationFile));
return this._sendFile(message,locationFile,media);
});
}
async _sendImageByUrl(message,uri) {
await this._sendFileByUrl(message,uri);
}
async _sendImage(message, filePath) {
this._sendFile(message,filePath, 1);
}
async _download(uri,name,type) {
let formatType;
switch (type) {
case 3:
formatType = 'm4a';
break;
default:
formatType = 'jpg';
break;
}
let dir = __dirname+'/../download';
if (!fs.existsSync(dir)){
await fs.mkdirSync(dir);
}
await unirest
.get(uri)
.headers({
...this.config.Headers
})
.end((res) => {
if(res.error) {
console.log(res.error);
return 'err';
}
}).pipe(fs.createWriteStream(`${dir}/${name}.${formatType}`));
}
async _sendFile(message,filepaths, typeContent = 1) {
let filename = 'media';
let typeFile;
switch (typeContent) {
case 2:
typeFile = 'video'
break;
case 3:
typeFile = 'audio'
break;
default:
typeFile = 'image'
break;
}
let M = new Message();
M.to = message.to;
M.contentType= typeContent;
M.contentPreview= null;
M.contentMetadata= null;
const filepath = path.resolve(__dirname,filepaths)
console.log('File Locate on',filepath);
fs.readFile(filepath,async (err, bufs) => {
let imgID = await this._client.sendMessage(0,M);
const data = {
params: JSON.stringify({
name: filename,
oid: imgID.id,
size: bufs.length,
type: typeFile,
ver: '1.0'
})
};
return this
.postContent(config.LINE_POST_CONTENT_URL, data, filepath)
.then((res) => {
if(res.err) {
console.log('err',res.error)
return;
}
console.log(res.headers);
if(filepath.search(/download\//g) === -1) {
fs.unlink(filepath, (err) => {
if (err) {
console.log('err on upload',err);
return err
};
console.log(`successfully deleted ${filepath}`);
});
}
});
});
}
postContent(url, data = null, filepath = null) {
return new Promise((resolve, reject) => (
unirest.post(url)
.headers({
...this.config.Headers,
'Content-Type': 'multipart/form-data'
})
.timeout(120000)
.field(data)
.attach('files', filepath)
.end((res) => {
if(res.err) {
console.error('error on post to server');
reject(res.error);
return;
}
resolve(res)
})
));
}
_fetchOperations(revision, count = 5) {
// this.options.path = this.config.LINE_POLL_URL
return this._client.fetchOperations(revision, count);
}
_fetchOps(revision, count = 5) {
return this._client.fetchOps(revision, count,0,0);
}
getJson(path) {
return new Promise((resolve, reject) => (
unirest.get(`https://${this.config.LINE_DOMAIN}${path}`)
.headers(this.config.Headers)
.timeout(120000)
.end((res) => (
res.error ? reject(res.error) : resolve(res.body)
))
));
}
}
module.exports = LineAPI;

80
src/command.js Normal file
View file

@ -0,0 +1,80 @@
const LineAPI = require('./api');
let exec = require('child_process').exec;
class Command extends LineAPI {
constructor() {
super();
this.spamName = [];
}
get payload() {
if(typeof this.messages !== 'undefined'){
return (this.messages.text !== null) ? this.messages.text.split(' ').splice(1) : '' ;
}
return false;
}
async getProfile() {
let { displayName } = await this._myProfile();
return displayName;
}
async cancelMember() {
let groupID;
if(this.payload.length > 0) {
let [ groups ] = await this._findGroupByName(this.payload.join(' '));
groupID = groups.id;
}
let gid = groupID || this.messages.to;
let { listPendingInvite } = await this.searchGroup(gid);
if(listPendingInvite.length > 0){
this._cancel(gid,listPendingInvite);
}
}
async searchGroup(gid) {
let listPendingInvite = [];
let thisgroup = await this._getGroups([gid]);
if(thisgroup[0].invitee !== null) {
listPendingInvite = thisgroup[0].invitee.map((key) => {
return key.mid;
});
}
let listMember = thisgroup[0].members.map((key) => {
return { mid: key.mid, dn: key.displayName };
});
return {
listMember,
listPendingInvite
}
}
async getSpeed() {
let curTime = Date.now() / 1000;
await this._sendMessage(this.messages, 'waiting...');
const rtime = (Date.now() / 1000) - curTime;
await this._sendMessage(this.messages, `${rtime} Second`);
return;
}
async kickAll() {
let groupID;
if(this.stateStatus.kick == 1) {
let updateGroup = await this._getGroup(this.messages.to);
updateGroup.name = '𝔑𝔬 𝔢𝔞𝔡';
await this._updateGroup(updateGroup);
this._sendMessage(this.messages, 'Ngantos Kepanggih Malih Asu');
let { listMember } = await this.searchGroup(this.messages.to);
for (var i = 0; i < listMember.length; i++) {
if(!this.isAdminOrBot(listMember[i].mid)){
this._kickMember(this.messages.to,[listMember[i].mid])
}
}
return;
}
}
}
module.exports = Command;

84
src/main.js Normal file
View file

@ -0,0 +1,84 @@
const Command = require('./command');
const { Message, OpType, Location, Profile } = require('../curve-thrift/line_types');
class LINE extends Command {
constructor() {
super();
this.receiverID = '';
this.checkReader = [];
this.stateStatus = {
cancel: 1,
kick: 1,
salam: 1
};
this.messages;
this.payload
}
get myBot() {
const bot = ['u1d55aeaa8b863cb338f4e8fd7a761b4b','u15ea9e62d7293bc69654e5e5f8a0053b','u277c188afb3f7632c261c58a79933360','u27dcf89bce7c8747107301e7b4424e08','u3a1641641abbf666b61a09221748d10c','u413abe1a4bbe3f646c8edab032fd6117','u43a4a9e76c47863e4a839b39b95c7047','u5ed385b3f578a1552439d75ada3eaea4','u605205b7305427eb778b499dbf4aebc8','u630ee831febbe7240973364570541171','u9882ac8a197b20f25cc21650f656fadd','ub1594fa0d3959eb82ac73675541d7ee0','ubc56b8fda25e78795ce157905a7fe6f2','ube3899df6730441eae28c3dc2f109249','uc687709232ddb16870499e0e9687c8ed','ue7afb5f5fd1b16902f22f29b9c9c9970','ufedfd6819d63f9235007cab688acebe7','u382280cbc27f30b9393b17d87ac4c569'];
return bot;
}
isAdminOrBot(param) {
return this.myBot.includes(param);
}
getOprationType(operations) {
for (let key in OpType) {
if(operations.type == OpType[key]) {
if(key !== 'NOTIFIED_UPDATE_PROFILE') {
console.info(`[* ${operations.type} ] ${key} `);
}
}
}
}
poll(operation) {
if(operation.type == 25 || operation.type == 26) {
let message = new Message(operation.message);
this.receiverID = message.to = (operation.message.to === this.myBot[0]) ? operation.message._from : operation.message.to ;
Object.assign(message,{ ct: operation.createdTime.toString() });
this.textMessage(message)
}
if(operation.type == 13) {
if(this.stateStatus.kick == 1) {
return this._acceptGroupInvitation(operation.param1);
}
}
this.getOprationType(operation);
}
command(msg, reply) {
if(this.messages.text !== null) {
if(this.messages.text === msg.trim()) {
if(typeof reply === 'function') {
reply();
return;
}
if(Array.isArray(reply)) {
reply.map((v) => {
this._sendMessage(this.messages, v);
})
return;
}
return this._sendMessage(this.messages, reply);
}
}
}
async textMessage(messages) {
this.messages = messages;
let payload = (this.messages.text !== null) ? this.messages.text.split(' ').splice(1).join(' ') : '' ;
let receiver = messages.to;
let sender = messages.from;
this.command('speed', this.getSpeed.bind(this));
this.command(`huhu ${payload}`,this.cancelMember.bind(this));
}
}
module.exports = LINE;