Git Product home page Git Product logo

nodemw's Introduction

nodemw

Node.js CI Coverage Status code style: prettier

MediaWiki API client written in node.js

Requirements

Installation

Using npm

npm install nodemw

Or Download the latest stable version via GitHub.

Development version

git clone https://github.com/macbre/nodemw.git

Features

  • HTTP requests are stored in the queue and performed in parallel with limited number of "threads" (i.e. there's no risk of flooding the server)
  • articles creation / edit / move / delete
  • file uploads (using given content or via provided URL)
  • Special:Log processing
  • listing articles in categories
  • and much more
  • getting claims from WikiData

Where it's used

First script

An example script can be found in /examples directory.

cd examples
node pagesInCategory.js

You can enter debug mode by setting DEBUG enviromental variable:

DEBUG=1 node examples/pagesInCategory.js

You can enter dry-run mode (all "write" operations like edits and uploads will be disabled) by setting DRY_RUN environmental variable (or dryRun entry in the config):

DRY_RUN=1 node examples/pagesInCategory.js

Running unit tests

npm test

How to use it?

Creating a bot instance

var bot = require("nodemw");

// pass configuration object
var client = new bot({
  protocol: "https", // Wikipedia now enforces HTTPS
  server: "en.wikipedia.org", // host name of MediaWiki-powered site
  path: "/w", // path to api.php script
  debug: false, // is more verbose when set to true
});

client.getArticle("foo", function (err, data) {
  // error handling
  if (err) {
    console.error(err);
    return;
  }

  // ...
});

Config file

nodemw can use config files as well as objects directly provided to bot object constructor.

// read config from external file
var client = new bot("config.js");

Config file is a JSON-encoded object with the following fields (see /examples/config-DIST.js file):

{
      "protocol": "https",  // default to 'http'
      "server": "en.wikipedia.org",  // host name of MediaWiki-powered site
      "path": "/w",                  // path to api.php script
      "debug": false,                // is more verbose when set to true
      "username": "foo",             // account to be used when logIn is called (optional)
      "password": "bar",             // password to be used when logIn is called (optional)
      "domain" : "auth.bar.net",     // domain to be used when logIn is called (optional)
      "userAgent": "Custom UA",      // define custom bot's user agent
      "concurrency": 5               // how many API requests can be run in parallel (defaults to 3)
}

Making direct API calls

nodemw allows you make direct calls to MediaWiki API (example querying Semantic MediaWiki API):

var bot = require("nodemw"),
  client = new bot({
    server: "semantic-mediawiki.org",
    path: "/w",
  }),
  params = {
    action: "ask",
    query:
      "[[Modification date::+]]|?Modification date|sort=Modification date|order=desc",
  };

client.api.call(
  params /* api.php parameters */,
  function (
    err /* Error instance or null */,
    info /* processed query result */,
    next /* more results? */,
    data /* raw data */,
  ) {
    console.log(data && data.query && data.query.results);
  },
);

Bot methods

The last parameter of each function in nodemw API is a callback which will be fired when the requested action is done.

Callbacks use node.js style - err is always passed as the first argument.

bot.logIn(username, password, callback)

Log-in using given credentials - read more

bot.getCategories(prefix, callback)

Gets the list of all categories on a wiki

bot.getAllPages(callback)

Gets the list of all pages from the main namespace (excludes redirects) - read more

bot.getPagesInCategory(category, callback)

Gets the list of pages in a given category - read more

bot.getPagesInNamespace(namespace, callback)

Gets the list of pages in a given namespace - read more

bot.getPagesByPrefix(prefix, callback)

Gets the list of pages by a given prefix - read more

bot.getPagesTranscluding(page, callback)

Gets the list of pages that transclude the given pages - read more

bot.getArticle(title, [redirect,] callback)

Gets article content and redirect info - read more

bot.getArticleRevisions(title, callback)

Gets all revisions of a given article - read more

bot.getArticleCategories(title, callback)

Gets all categories a given article is in - read more

bot.getArticleInfo(title, callback)

Gets all info of a given article - read more

bot.edit(title, content, summary, minor, callback)

Creates / edits an article (and mark the edit as minor if minor is set to true) - read more

bot.append(title, content, summary, callback)

Adds given content to the end of the page - read more

bot.prepend(title, content, summary, callback)

Adds given content to the beginning of the page - read more

bot.addFlowTopic(title, topic, content, callback)

Add a Flow topic - read more

bot.delete(title, reason, callback)

Deletes an article - read more

bot.purge(titles, callback)

Purge a given list of articles (titles or page IDs can be provided) - read more

By providing Category:Foo as titles argument you can purge all pages in a given category (available since MW 1.21)

bot.protect(title, protections, options, callback)

Protect a page (A title or page ID can be provided) - read more

The protections value is an Array of protection information in the format:

{
    action: string,
    level?: string = 'all',
    expiry?: string | number = 'never'
}

Calls to the Protect endpoint are not additive. Each call must include a list of all intended protections, including any already in place. Each call will replace all existing protections.

bot.sendEmail(username, subject, text, callback)

Send an email to an user - read more

bot.getToken(title, action, callback)

Returns token required for a number of MediaWiki API operations - read more / for MW 1.24+

bot.whoami(callback)

Gets information about current bot's user (including rights and rate limits) - read more

bot.whois(username, callback)

Gets information about a specific user (including rights, current block, groups) - read more

bot.whoare(usernames, callback)

Gets information about specific users (including rights, current block, groups) - read more

bot.createAccount(username, password, callback)

Create account using given credentials - read more

bot.move(from, to, summary, callback)

Moves (aka renames) given article - read more

bot.getImages(callback)

Gets list of all images on a wiki

bot.getImageUsage(filename, callback)

Gets list of all articles using given image

bot.getImagesFromArticle(title, callback)

Get list of all images that are used on a given page - read more

bot.getImageInfo(filename, callback)

Gets metadata (including uploader, size, dimensions and EXIF data) of given image

bot.getLog(type, start, callback)

Get entries form Special:Log - read more

bot.expandTemplates(content, title, callback)

Returns XML with preprocessed wikitext - read more

bot.parse(content, title, callback)

Returns parsed wikitext - read more

bot.fetchUrl(url, callback)

Makes a GET request to provided resource and returns its content.

bot.getRecentChanges(start, callback)

Returns entries from recent changes (starting from a given point)

bot.getSiteInfo(props, callback)

Returns site information entries - read more

bot.getSiteStats(props, callback)

Returns site statistics (number of articles, edits etc) - read more

bot.getMediaWikiVersion(callback)

Returns the version of MediaWiki given site uses - read more

client.getQueryPage(queryPage, callback)

Returns entries from QueryPage-based special pages

bot.upload(filename, content, summary /* or extraParams */, callback)

Uploads a given raw content as a File:[filename] - read more

bot.uploadByUrl(filename, url, summary /* or extraParams */, callback)

Uploads a given external resource as a File:[filename]

bot.uploadVideo(fileName, url, callback)

Uploads a given video as a File:[filename] (Wikia-specific API)

bot.getTemplateParamFromXml(tmplXml, paramName)

Gets a value of a given template parameter from article's preparsed content (see expandTemplates)

bot.getExternalLinks(title, callback)

Gets all external links used in article

bot.getBacklinks(title, callback)

Gets all articles that links to given article

bot.search(query, callback)

Performs a search

Helpers

bot.getConfig(key, def)

Gets config entry value (returns def value if not found)

bot.setConfig(key, val)

Sets config entry value

bot.diff(old, current)

Returns a diff colored using ANSI colors (powered by diff)

Wikia-specific bot methods

They're grouped in bot.wikia "namespace".

bot.wikia.getWikiVariables(callback)

Get wiki-specific settings (like ThemeDesigner colors and hubs).

bot.wikia.getUser(userId, callback)

Get information (avatar, number of edits) about a given user

bot.wikia.getUsers(userIds, callback)

Get information (avatar, number of edits) about a given set of users (by their IDs)

This API is Promise-based, use await keyword.

Examples:

const wikidata = require("nodemw/lib/wikidata");
const client = new wikidata();

// Where is Saksun, Faroe Islands located?
const geo = await client.getEntityClaim(
  "Q928875" /* Saksun */,
  "P625" /* place location */,
);

// will give you the geolocation of the place
expect(geo[0].mainsnak.datavalue.value).toMatchObject({
  latitude: 62.248888888889,
  longitude: -7.1758333333333,
});

// When was Albert Einstein born?
const res = await client.getArticleClaims("Albert Einstein");

const dateOfBirth = res.P569[0].mainsnak.datavalue.value;
expect(dateOfBirth.time).toMatch(/1879-03-14/);

const dateOfDeath = res.P570[0].mainsnak.datavalue.value;
expect(dateOfDeath.time).toMatch(/1955-04-18/);

// interwiki links for a given artlice
const links = await client.getArticleSitelinks("Albert Einstein");
console.log(links.enwiki); // {site: "enwiki", title: "Albert Einstein", badges: ["Q17437798"]}

Stargazers over time

Stargazers over time

nodemw's People

Contributors

andrewnicols avatar brendan-jefferis avatar cr0wst avatar dependabot[bot] avatar divdavem avatar fannon avatar g-sun avatar hakubo avatar juul avatar jwbth avatar kcivey avatar krenair avatar krinkle avatar kyv avatar lagleki avatar macbre avatar marcinpl87 avatar maxkueng avatar nicroto avatar robocopklaus avatar sanym avatar snyk-bot avatar stdob avatar tarang avatar technical-13 avatar valentinbrclz avatar webmajstr avatar zeljkofilipin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nodemw's Issues

Don't print any debug information unless debug option is true

  • The library should be completely silent unless the debug option is set to either true or a debug level ("info", "debug")
  • The debug option should be false by default

Reason: It's currently impossible to not have an app print stuff to the console.

api.call -> token must be sent as POST parameter

Hello!

I'm using the api.call method for editing pages, because I needed to adjust some more advanced parameters. The wiki of course needs the token in order to do this, but I can't send it through the parameters:

code="mustposttoken" info="The token parameter was found in the query string, but must be in the POST body"

If I don't set the token parameter I'll get The token parameter must be set

Best,
Simon

Cannot read property 'result' of undefined

This happens if mediawiki crashes (PHP error) to nodemw:

Maybe this is something you should check and return as an err callback instead.
Thanks for introducing this, btw!

TypeError: Cannot read property 'result' of undefined
at [...]\node_modules\nodemw\lib\bot.js:299:22

support for https

support for https config would be great. I've implemented it locally, but it's a minor change.

info result

I'd like to implement support for Semantic Mediawiki's ask.

http://semantic-mediawiki.org/wiki/Ask_API

however, while the action is ask, it doesn't populate data[ask] as api.js expects. it uses data[results].

is there a good way to resolve this?

thanks!

Wikia: support video uploads

Example

const url = 'https://www.youtube.com/watch?v=24X9FpeSASY'; // or https://vimeo.com/27986705

client.wikia.uploadVideo(fileName, url, (err, res) => {
  // ...
});

API request parameters

action=addmediapermanent

  • title
  • provider
  • videoId
  • token

Supported videos

YouTube

https://github.com/Wikia/app/blob/dev/extensions/wikia/VideoHandlers/apiwrappers/YoutubeApiWrapper.class.php

provider: youtube
id: axu2ju-HwTg

Vimeo

https://github.com/Wikia/app/blob/dev/extensions/wikia/VideoHandlers/apiwrappers/VimeoApiWrapper.class.php

provider: vimeo
id: 27986705

Cannot read property 'info' of undefined api.js:206

The error handling seems a bit shaky. When doing an ask query (Semantic MediaWiki) the info variable is undefined even though data.query.results has results. This causes the response to fall through all the ifs all they way town to the else case even though there is actually no error. And then crashes on api.js:206 because data.error is undefined.

I think this part of the code should only run if there actually is an error i.e. typeof data.error !== 'undefined'.

This is my params object for client.api.call:

{
  action: 'ask',
  query: '[[Category:SIP Phone]]|?User'
};

and this is what the data variable contains:

{ query: 
   { printrequests: [ [Object], [Object] ],
     results: { 'SIP Phone 60': [Object], 'SIP Phone 61': [Object] },
     serializer: 'SMW\\Serializers\\QueryResultSerializer',
     version: 0.5,
     meta: { hash: 'd82a813f78da82e1d9b94acaee6e37c5', count: 2, offset: 0 } } }

and this is the complete error:

Debug: internal, implementation, error 
    TypeError: Cannot read property 'info' of undefined
    at Request._callback (/home/max/projects/xml-phonebook/node_modules/nodemw/lib/api.js:208:63)
    at Request.self.callback (/home/max/projects/xml-phonebook/node_modules/nodemw/node_modules/request/request.js:199:22)
    at Request.emit (events.js:98:17)
    at Request.<anonymous> (/home/max/projects/xml-phonebook/node_modules/nodemw/node_modules/request/request.js:1160:14)
    at Request.emit (events.js:117:20)
    at IncomingMessage.<anonymous> (/home/max/projects/xml-phonebook/node_modules/nodemw/node_modules/request/request.js:1111:12)
    at IncomingMessage.emit (events.js:117:20)
    at _stream_readable.js:944:16
    at process._tickDomainCallback (node.js:486:13)

TL;DR: It tries to report an error even though everything went fine.

Promise sometimes rejected multiple times

Both of these promise rejections can happen at the same time, which throws an error in deferred.js. (Aside: I've read that in some promise implementations, the second rejection is treated as a noop.)

Not sure what the best way to solve this is. It's nice to get the info for both errors, but it's not nice for the server to crash. Maybe could test each case separately, without rejecting, then do one combined rejection after both if statements?

Creating users

I am writing Selenium tests for mediawiki/core and I would like to speed up some tests by using the API instead of the web interface.

Am I missing it, or is there no built-in way of creating users?

Is making direct API calls the only way to go?

getImagesFromArticle() method failing

Hello,

I'm trying to use the getImagesFromArticle call on the bot and I'm not sure what I'm doing wrong, but it doesn't seem to be working the way it is supposed to. This is how I'm calling it:

client.getImagesFromArticle(bodyParsed[i].comName, function (err, data) {
    if (err) { console.error(err) }
    console.log('images: ');
    console.log(data);
})

Here is where the problem occurs:

20150409_011112

Any suggestions are much appreciated! Thanks!

Token error when editing

Hello,

I often encounter token errors (Error: Invalid token) and after doing some changes to my code, I realised that the error was made because of the concurrency of the requests.

I guess that a token has to be used directly to successfully edit a page. If a second token is asked in the meantime, the edit will fail with the aforementioned error.

Best regards,
Val'

what is the format of output of getArticle?

How do I parse the output returned from getArticle? It doenst seems like json .

{{about||the technology company|Apple Inc.|other uses}}
{{redirect|Apple tree}}
{{pp-semi-indef}}
{{pp-move-indef}}
{{Use dmy dates|date=January 2015}}
{{good article}}
{{taxobox
|name = Apple
|image = Red Apple.jpg
|image_caption = Fruit
|image2 = File:Malus domestica a1.jpg
|image2_caption = Flowers
|regnum = [[Plant]]ae
|unranked_divisio = [[Angiosperms]]
|unranked_classis = [[Eudicots]]
|unranked_ordo = [[Rosids]]
|ordo = [[Rosales]]
|familia = [[Rosaceae]]
|genus = ''[[Malus]]''
|species = '''''M. domestica'''''
|binomial = ''Malus domestica''
|binomial_authority = [[Moritz Balthasar Borkhausen|Borkh.]], 1803
|synonyms = ''Malus communis'' <small>Desf.</small><br/>
''Malus pumila'' <small>auct.</small><ref>{{GRIN | name = ''Malus pumila'' auct. | id = 410495 | accessdate = 4 January 2012}}</ref><br/>
''Pyrus malus'' <small>L.</small><ref>{{GRIN | name = ''Pyrus malus'' L. | id = 30530 | accessdate = 29 January 2012}}</ref>
|}}
The '''apple tree''' (''Malus domestica'') is a [[deciduous]] [[tree]] in the [[Rosaceae|rose family]] best known for its sweet, [[pome|pomaceous]] [[fruit]], the '''apple'''. It is [[agriculture|cultivated]] worldwide as a [[fruit tree]], and is the most widely grown species in the [[genus]] ''[[Malus]]. ''The tree originated in [[Central Asia]], where its wild ancestor, ''[[Malus sieversii]]'', is still found today. Apples have been grown for thousands of years in Asia and Europe, and were brought to North America by European colonists. Apples have [[religion|religious]] and [[mythology|mythological]] significance in many cultures, including [[Norse mythology|Norse]], [[Greek mythology|Greek]] and European Christian traditions.

Error: write EPIPE on 0.10.32

wondering if you might know why some simple code throws this error on 0.10.32, yet it works fine on 0.10.30?

thanks!

calling edit w/o a callback

Looks like it crashes if you don't specify an edit callback. Should probably be changed to callback && callback() like the other helper functions have it?

Revisions content

Hello, is it possible to get revisions content through bot.getArticleCategories(title, callback)?

how to catch econnresets?

Every now and then I get one of these when I make an edit request:

Socket error: socket hang up (ECONNRESET)
Error: socket hang up
    at createHangUpError (http.js:1263:15)
    at Socket.socketOnEnd [as onend] (http.js:1351:23)
    at TCP.onread (net.js:417:26)

I tried catching it by adding the following to doRequest():

req.on('socket', function(socket) {
    socket.on('error', function(e) {
        console.log("SOCKET ERROR:",e);
    });
});

but to no avail. Any idea how to catch these? They happen very rarely--once every few hundred requests.

Implement getSiteInfo method

// props defaults to [ 'statistics' ]
client.getSiteInfo(props, function(err, info) {
  console.log(info.statistics.edits);
});

Exception thrown when ECONNRESET is not caught

error:   Request to API failed: %s code=ECONNRESET

TypeError: Cannot read property 'statusCode' of undefined
    at Request._callback (/home/macbre/github/pyrabot/node_modules/nodemw/lib/api.js:166:16)
    at self.callback (/home/macbre/github/pyrabot/node_modules/nodemw/node_modules/request/request.js:129:22)

Possible bug in upload handling (when other parameters are provided)

Note that this only happens when other parameters are provided. The summary-only parameters seem to work fine for some reason. I'm using iojs v2.1.0.

Triggering code (very simple):

        async.each(Object.keys(nameToUrls), function(file, cb) {
            var from = nameToUrls[file];
            bot.uploadByUrl(file, from, { text: 'some text',
                comment: 'autoupload file',
                ignorewarnings: false }, function(err, res) {
                if (err) {
                    logger.error('Unable to upload ' + file, err);
                    return cb();
                }

                logger.info('Uploaded ' + file + ' from ' + from);
                cb();
            });
        }, function() {
            logger.info('Uploaded ' + lang);
        });

Error:

error:   Unable to upload <file>
Error: Request to API failed:     Error: Argument error, options.body.
    at Request._callback (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/lib/api.js:162:14)
    at self.callback (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/request.js:354:22)
    at emitOne (events.js:77:13)
    at Request.emit (events.js:169:7)
    at Request.init (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/request.js:609:12)
    at new Request (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/request.js:265:8)
    at request (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/index.js:56:10)
    at Object.module.exports.doRequest (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/lib/api.js:157:3)
    at Object.<anonymous> (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/lib/api.js:236:15)
    at /home/tux/IdeaProjects/archivesbot/node_modules/nodemw/lib/api.js:59:4
_http_outgoing.js:429
        throw new TypeError('first argument must be a string or Buffer');
              ^
TypeError: first argument must be a string or Buffer
    at ClientRequest.OutgoingMessage.write (_http_outgoing.js:429:11)
    at Request.write (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/request.js:1510:25)
    at /home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/request.js:703:18
    at Array.forEach (native)
    at end (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/request.js:702:21)
    at Immediate._onImmediate (/home/tux/IdeaProjects/archivesbot/node_modules/nodemw/node_modules/request/request.js:734:7)
    at processImmediate [as _immediateCallback] (timers.js:368:17)

Introduce dry run mode

Enter via config's dryRun entry set to true or DRY_RUN env variable set.

Do not perform any "write" operations: edits, moves, deletes, uploads when in dry run mode.

Add automatic continuation for "getPagesInCategory"?

Do you mind adding a automatic continuation mechanism for getPagesInCategory? Because right now, it will stop after 500 entries. Any "cmlimit" value over 500 has no effect either (due to wikimedia).

I tried something fast (without fully reading through all the code).

This does the job for me:

I replaced:

this.api.call({
    action: 'query',
    list: 'categorymembers',
    cmtitle: category,
    cmlimit: 5000
}, function(err, data) {
    callback(err, data && data.categorymembers || []);
});

with:

this.getAll(
    {
        action: 'query',
        list: 'categorymembers',
        cmtitle: category,
        cmlimit: 5000,
        cmtype: 'page',
        rawcontinue: true
    },
    'categorymembers',
    callback
);

inside "getPagesInCategory".

No idea if it is complete BS though.

Add error check in bot.getToken function

error:   Request to API failed: %s Error: read ECONNRESET
    at errnoException (net.js:904:11)
    at TCP.onread (net.js:558:19)

TypeError: Cannot read property 'pages' of undefined
    at /home/macbre/github/pyrabot/node_modules/nodemw/lib/bot.js:387:33
    at Request._callback (/home/macbre/github/pyrabot/node_modules/nodemw/lib/api.js:162:5)
    at self.callback (/home/macbre/github/pyrabot/node_modules/nodemw/node_modules/request/request.js:354:22)
    at Request.emit (events.js:95:17)
    at Request.onRequestError (/home/macbre/github/pyrabot/node_modules/nodemw/node_modules/request/request.js:1011:8)
    at ClientRequest.emit (events.js:95:17)
    at Socket.socketErrorListener (http.js:1547:9)
    at Socket.emit (events.js:95:17)
    at net.js:440:14
    at process._tickCallback (node.js:419:13)

Introduce Wikia API methods

Docs: http://www.wikia.com/api/v1

// @see http://poznan.wikia.com/api/v1/Mercury/WikiVariables
client.wikia.getWikiVariables(function(err, vars) {
  console.log(vars.theme['color-links']); // #006cb0
  console.log(vars.wikiCategories); // ["travel"]
});

// @see http://poznan.wikia.com/api/v1/User/Details?ids=119245&size=50
client.wikia.getUser(userId, function(err, function(err, user) {
  console.log(user.avatar);
  console.log(user.numberofedits);
});

// @see http://poznan.wikia.com/api/v1/User/Details?ids=1,119245&size=50
// Maximum size of id list is 100.
client.wikia.getUsers([user1Id, user2Id], function(err, function(err, users) {
  console.log(users[0].avatar);
  console.log(users[0].numberofedits);

  console.log(users[1].avatar);
  console.log(users[1].numberofedits);
});

Use node-style callbacks throughout

Callbacks should be passed an Error as the first argument and data as the second.

Like so:

client.logIn(function (err, data) {
  if (err) { return console.log('login failed', err); }

  console.log('login successful', data);
});

Instead of:

client.logIn(function (data) {
  console.log('maybe login successful', data);
});

Encourage non-conflicting edits

When making changes to existing content (e.g. not appending or prepending text), it is important that bots don't accidentally overwrite edits by other users.

The way bots should do this to, when fetching the existing content, pass the revision timestamp to the edit module. This way, if another edit has been made since then, the edit will be rejected. At this point the bot can either try again, or skip the item for the time being.

mwbot provides a getArticle method, but it doesn't expose any meta data besides the page content.

Please provide an easy way for developers to use mwbot to make edits in a way that doesn't cause human edits to be overwritten by default. It should perhaps be an option to ignore conflicts, but by default it probably should not ignore conflicts.

Ideas:

// getPage(string name) -> API query revisions, rvprop=content|timestamp
client.getPage(name, function (err, data) {
  // data.title
  // data.content
  // data.timestamp

  var newContent = change(data.content);

  // Method 1: edit( pageName, content, summary, params, callback )
  client.edit(data.title, newContent, '', { basetimestamp: data.timestamp, fn(err,data) });

  // Method 2: edit( string|Object pageData, content, summary, calllback )
  client.edit(data, newContent, '', function (err, data) { });
});

The second method is probably easiest and encourages developers to use it without hardcoding details of parameters.

Introduce promise pattern and improve errors handling

What's the best way to catch api errors? For example, I want to catch "Page doesn't exist" errors when I try to delete pages that don't exist, but surrounding bot.delete() calls in a try/catch doesn't seem to work.

Cannot call edit (error null)

I am using script depending both on nodemw and disconnect (by @bartve [https://github.com/bartve/disconnect]).

Method "edit" always ends up returning following error in callback: "Edit failed: null"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.