/instapy-tools

Tools for building on top of InstapPy!

Primary LanguageTypeScriptGNU General Public License v3.0GPL-3.0

Instapy-Tools

Note: this lib is pre v1 stage, expect thing breaking/buggy.

Want to build on top of Instapy? Then this is the toolset for you!

Batteries included:

  • Ability to generate machine readable api in JSON format from python code
  • Be able to controle the bot directly from js, using docker-compose
  • TypeScript InstaPy api, generated from api.json (comming soon™)

Requirements:

  • node > 10
  • docker
  • docker-compose
  • linux, Note: Using windows/mac and it works somehow let me now :)

Usage

Api from generated api.json

import and extract api methods

import { api } from 'instapy-tools'

const { raw
      , setupValidateMethod
      , setupMethod
      , setupCreate
      , setupArgComponent
      , setupInterface
      } = api

getting the raw jsonApiObj (api.json)

console.log(raw) // thats it...

setting up and using validateMethod

// setup
const validateMethod = setupValidateMethod(raw)

//usage
const validatedMethod1 =
  validateMethod
  ( { name: 'like_by_tags'
    , args:
      { tags: ['#cats', '#coolcats', '#aliencatsinspace']
      , amount: 50
      }
    }
  )
console.log(validatedMethod1) // true

const validatedMethod2 =
  validateMethod
  ( { name: 'like_by_tags'
    , args:
      { tags: ['#cats', '#coolcats', '#aliencatsinspace']
      , usernames: ['#user1', '#user2'] // dosen't exist on the method
      }
    }
  )
console.log(validatedMethod2) // false

const validatedMethod3 =
  validateMethod
  ( { name: 'like_by_tags'
    , args:
      { tags: ['#cats', '#coolcats', '#aliencatsinspace']
      , amount: -1 // lower than the constraint
      }
    }
  )
console.log(validatedMethod3) // false

setting up and using method

const method = setupMethod(raw) // uses 'session' as default name for the sessionObject
const methodBot = setupMethod(raw, 'bot') // now uses 'bot' for the sessionObject

const methodLine1 =
  method
  ( { name: 'like_by_tags'
    , args:
      { tags: ['#cats', '#coolcats', '#aliencatsinspace']
      , amount: 50
      }
    }
  )

const methodLine1Bot =
  methodBot
  ( { name: 'like_by_tags'
    , args:
      { tags: ['#cats', '#coolcats', '#aliencatsinspace']
      , amount: 50
      }
    }
  )

console.log(methodLine1) // 'session.like_by_tags(tags=['#cats', '#coolcats', 'aliencatsinspace'], amount=50)'
console.log(methodLine1Bot) // 'bot.like_by_tags(tags=['#cats', '#coolcats', 'aliencatsinspace'], amount=50)'
special case for the initializer
const methodInit =
  method
  ( { name: '__init__'
    , args:
      { username: 'userName'
      , password: 'passWord'
      }
    }
  )

console.log(methodInit) // session = InstaPy(username='userName', password='passWord')

Seting up and using create

const create = setupCreate() // normal run, uses default InstaPyPath
const smartRunCreate = setupCreate(true) // uses smart_run, default InstaPyPath
const create = setupCreate(false, '/path/to/instapy/project')

const config =
  create
  ( [ method({name: '__init__', args: {someArgs...}})
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , '# a python comment in the code'
    , method(with some input...)
    , method(with some input...)
    , method({name: 'end'})
    ]
  )
  
const smartConfig =
  create
  ( [ method({name: '__init__', args: {someArgs...}})
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , method(with some input...)
    , '# a python comment in the code'
    , method(with some input...)
    , method(with some input...)
    , method({name: 'end'})
    ]
  )

console.log(config)
/*
from instapy import InstaPy
from instapy.util import smart_run

session = InstaPy(...)
session.method(...)
session.method(...)
session.method(...)
session.method(...)
session.method(...)
session.method(...)
session.method(...)
# a python comment in the code
session.method(...)
session.method(...)
session.end()
*/

console.log(smartConfig)
/*
from instapy import InstaPy
from instapy.util import smart_run

session = InstaPy(...)
with smart_run(session):
    session.method(...)
    session.method(...)
    session.method(...)
    session.method(...)
    session.method(...)
    session.method(...)
    session.method(...)
    # a python comment in the code
    session.method(...)
    session.method(...)
    session.end()
*/

create([...string], true) // will write the output to 'docker_quickstart.py'
create([...string], true, 'my-config.py') // will write the output to 'my-config.py'

Setup interface/ setup arg component

To "easily" generate an ui from api.json use these functions setupInterface and setupArgComponent

// def: default value given to argComponent
// argName: name given of argument
const fallbackComponent =
  (def, argName) => {
    // gets returned when it couldn't make out the type
    console.log(`${argName} has Type: fallback with default: ${def}`)
  }

const noneComponent =
  (def, argName) => () => {
    console.log(`${argName} has Type: None with default: ${def}`)
  }

const booleanComponent =
  (def, argName) => () => {
    console.log(`${argName} has Type: Boolean with default: ${def}`)
  }

const stringComponent =
  (def, argName) => () => {
    console.log(`${argName} has Type: String with default: ${def}`)
  }

// _constraints:
// { _step: undefined | number
// , _min: undefined | number
// , _max: undefined | number
// }
const numberComponent =
  (_constraints) => (def, argName) => () => {
    console.log(`${argName}, Type: Number, default: ${def}`)
  }

// _subType: 'Number' | 'String'  // Note: It is never 'Number'
const arrayComponent =
  (_subType) => (def, argName) => () => {
    console.log(`${argName}, Type: Array, default: ${def}`)
  }

// _subTypes list of all the types in order
const tupleComponent =
  (_subTypes) => (def, argName) => () => {
    // _subTypes.map(argComponent) <- use something like this here
    console.log(`${argName}, Type: Tuple, default: ${def}`)
  }

// _options: list of Types, Numbers and Strings
const unionComponent =
  (_options) => (def, argName) => () => {
    console.log(`${argName}, Type: Union, default: ${def}`)
  }

const argComponent =
  setupArgComponent
  ( { _default: fallbackComponent
    , boolean: booleanComponent
    , string: stringComponent
    , number: numberComponent
    , array: arrayComponent
    , tuple: tupleComponent
    , union: unionComponent
    }
  )

// args: { argName: buildArg } from raw.<methodName>.args
// methodName: said name of method from raw.<methodName>
const methodComponent =
  (args, methodName) => () => {
    //do everything you need to do
    console.log(methodName)
    if (args !== undefined) {
      if (args.enabled !== undefined) {
        args.enabled()
      }
      if (args.percentage !== undefined) {
        args.percentage()
      }
      if (args.times !== undefined) {
        args.times()
      }
    }
  }

const interface =
  setupInterface
  ( raw
  , methodComponent
  , argComponent
  )

interface.set_do_follow()
// set_do_follow
// enabled, Type: Union, default: false
// percentage, Type: Union, default: 0
// times, Type: Number, default: 1

Control bot from TS/JS

Setup controls

import { setupControls } from 'instapy-tools'

const controls = setupControls('Instapy') // Takes a string location to InstaPy Project Location

controls
  .start()
  .then( (val:any) => {console.log(val)}) // Bot started

start

// Starts bot using docker-compose
// Uses "docker_quickstart.py" as configuration file taken from InstaPy Project path
controls
  .start()
  .then( (val:any) => {console.log(val)}) // Bot started

stop

// Stops bot using docker-compose
controls
  .stop()
  .then( (val:any) => {console.log(val)}) // Bot stopped

status

// Watch bot-status using docker-compose
// returns: 'Not Initialised' | 'Done' | 'Running' | 'Stopped'
// (status: string) => {}
status()
  .then( (val:any) => {console.log(val)}) // Done

// Give a function to set that gets called everytime botStatus get changed.
controls
  .status
  .set( (botStatus:string) => { console.log(botStatus) })

// Remove given function
controls
  .status
  .reset()

logs

// Watch bot-logs using docker-compose
// returns: a log line concurrently at InstaPy's output

// Give a function to set that gets called everytime a new log is given
// (logLine: string) => {}
controls
  .logs
  .set((logLine: string) => {console.log(logLine)} )

// Attaching to instapy_web_1...
// web_1_3e4... | --2018-12-19 ...
// ''           | Resolving...

// Remove given function
controls
  .logs
  .reset()

Generating api.json

Deprecated this kind of functionality will be moved to InstaPy soon, hopefully

Cloning InstaPy Project

npm run instapy:clone

Updating InstaPy

npm run instapy:update

Generate api.json

npm run gen-api

Develop api.json

npm run gen-api:dev

Updating and publishing the Project

npm version <major | minor | patch>
npm publish

To-Do

  • generate api.json, 'including types'
  • expose api generated from api.json
  • add bot controls