Massfollowing - a mass subscription to people according to certain criteria.Services for massfollowing already exist long ago, 2 years ago I noticed the activity of my friends on Instagram, namely, the desire to promote my business through this social network. To do this, they used different mass subscription services, where a monthly subscription costs about 1000 rubles, and according to them, the effect is quite noticeable, especially for restaurants, food delivery services.
In simple language, you subscribe to a person, he sees in the tape that someone has subscribed to him, goes to your page.
')
On this goal, this tool for business is completed.
const UserSchema = new db.mongoose.Schema({ id: { type: Number, required: [true, 'idRequired'] }, name: { type: String, required: [true, 'nameRequired'] }, date: { type: Date, default: Date.now } })
const AccountSchema = new db.mongoose.Schema({ user: { type: Number, required: [true, 'userRequired'] }, login: { type: String, required: [true, 'loginRequired'] }, password: { type: String, required: [true, 'passwordRequired'] }, verified: { type: Boolean, default: false }, date: { type: Date, default: Date.now } })
const TaskSchema = new db.mongoose.Schema({ user: { type: Number, required: [true, 'userRequired'] }, login: { type: String, required: [true, 'loginRequired'] }, type: { type: String, required: [true, 'typeRequired'] }, params: { type: Object, required: [true, 'paramsRequired'] }, status: { type: String, default: 'active' }, date: { type: Date, default: Date.now }, start: { type: Number, required: [true, 'startReqiured'] } })
params
property, we store specific data for a specific task, for example, for a subscription:
sourceType | Source type (user, hashtag, location) |
source | source name (username, # hashtag, [lat, long]) |
actionFollow | total number of subscriptions / formal replies |
actionFollowDay | number of actions per day |
actionLikeDay | number of likes to each user |
module.exports = { event: 'home', children: { ' ': { event: 'task:create', children: { '*': { event: 'task:select', children: { ' + ': { event: 'task:select:follow+like', children: { : { event: 'task:select:follow+like:user', children: { '*': { event: 'task:select:follow+like:user:select', children: { '*': { event: 'task:select:follow+like:source:action', children: { '*': { event: 'task:select:follow+like:source:actionPerDay', children: { '*': { event: 'task:select:follow+like:source:like' } } }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'task:select:follow+like:hashtag', children: { '*': { event: 'task:select:follow+like:hashtag:find', children: { '*': { event: 'task:select:follow+like:source:action', children: { '*': { event: 'task:select:follow+like:source:actionPerDay', children: { '*': { event: 'task:select:follow+like:source:like' } } }, : { event: 'location:back' } } }, : { event: 'location:back' } } } } }, : { event: 'task:select:follow+like:source', children: { '*': { event: 'task:select:follow+like:source:select', children: { '*': { event: 'task:select:follow+like:source:action', children: { '*': { event: 'task:select:follow+like:source:actionPerDay', children: { '*': { event: 'task:select:follow+like:source:like' }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'task:select:type', children: { '*': { event: 'task:select:type:unfollow' // await: true }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, ' ': { event: 'account:add', children: { '*': { event: 'account:await', await: true }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'actions', children: { '*': { event: 'actions:account', children: { : { event: 'actions:account:update', children: { '*': { event: 'actions:account:update:one', children: { '*': { event: 'actions:account:update:two', children: { '*': { event: 'actions:account:update:three' } } } } }, : { event: 'location:back' } } }, : { event: 'actions:account:cancel' }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'account:list', children: { '*': { event: 'account:select', children: { : { event: 'account:edit', children: { '*': { event: 'account:edit:await', await: true }, : { event: 'location:back' } } }, : { event: 'account:delete', await: true }, : { event: 'location:back' } } }, ' ': { event: 'account:add', children: { '*': { event: 'account:await', await: true }, : { event: 'location:back' } } }, : { event: 'location:back' } } }, : { event: 'limit:message', children: { : { event: 'location:back' } } } } }
state = { 23445432: [' ', ' + '], 1345532: [''] }
const router = msg => { // if (msg.text) msg.text = emoji.decode(msg.text) // No user status, we give the main menu if (!state[msg.from.id]) { commandEvents.emit('/home', msg) // Adding the user to the state state[msg.from.id] = [] } else { // Go to the desired branch const findBranch = state[msg.from.id].reduce((path, item) => { // If there are no child partitions if (!path.children) { return path } else { if (path.children[item]) { return path.children[item] } else { // If there is no suitable branch, then we try to use a common branch if (path.children['*']) { return path.children['*'] } else { return path } } } }, map) // Call branch method const callBranch = branch => { const action = findBranch.children[branch] // Call action event.emit(action.event, msg, action, (value = msg.text) => { event.emit('location:next', msg, action, value) }) } // We check the existence of the method if (findBranch.children.hasOwnProperty(msg.text)) { callBranch(msg.text) } else if (findBranch.children['*']) { // If there is no suitable branch, then we try to use a common branch callBranch('*') } else { // back event.emit('location:back', msg) } } }
event.on('account:list', async (msg, action, next) => { try { const list = await Account.list(msg.from.id) if (list === null) { throw new Error(`There are no accounts for ${msg.from.id}`) } // Sending the list of accounts const elements = list.map(item => item.login) send.keyboard(msg.from.id, ' ', [ ...elements, ' ', '' ]) next && next() } catch (e) { event.emit('account:empty', msg) next && next() } })
cron.schedule(conf.cron, async () => { try { const list = await task.currentList() if (list === null) throw new Error('No active assignments') for (let item of list) { const id = item._id.toString() // Missing running tasks if (activeTask.includes(id)) continue switch (item.type) { case ' + ': activeTask.push(id) actions .followLike(item) .then(res => { // Remove from list const keyActiveTask = activeTask.indexOf(id) delete activeTask[keyActiveTask] if (res.name === 'AuthenticationError') { send.message( item.user, `️ ${item.login} , !` ) throw new Error(' ') } // notify the user when the task is completed if (res) { send.message( item.user, ` ${item.type} ${item.login}` ) } }) .catch(e => console.log(e)) break case '': activeTask.push(id) actions .unFollow(item) .then(res => { // Remove from list const keyActiveTask = activeTask.indexOf(id) delete activeTask[keyActiveTask] if (res.name === 'AuthenticationError') { send.message( item.user, `️ ${item.login} , !` ) throw new Error(' ') } // notify the user when the task is completed if (res) { send.message( item.user, ` ${item.type} ${item.login}` ) } }) .catch(e => console.log(e)) break default: // Job type is not defined break } } } catch (e) { // No active assignments return e } })
Source: https://habr.com/ru/post/355014/