mirror of
https://github.com/sstent/node_app.git
synced 2026-01-27 07:31:58 +00:00
adding test code for reading garmin connect
This commit is contained in:
456
node_modules/mongoskin/Readme.md
generated
vendored
456
node_modules/mongoskin/Readme.md
generated
vendored
@@ -1,11 +1,25 @@
|
||||
## This project is a wrapper of node-mongodb-native
|
||||
# mongoskin
|
||||
|
||||
* node-mongodb-native document http://christkv.github.com/node-mongodb-native/
|
||||
[](http://travis-ci.org/kissjs/node-mongoskin)
|
||||
|
||||
## How to validate input?
|
||||
This project is a wrapper of [node-mongodb-native](https://github.com/mongodb/node-mongodb-native).
|
||||
The api is same to node-mongodb-native, please see the [document](http://mongodb.github.com/node-mongodb-native/) first.
|
||||
|
||||
I wrote a middleware to validate post data, [node-iform](https://github.com/guileen/node-iform)
|
||||
base on [node-validator](https://github.com/chriso/node-validator)
|
||||
## Test
|
||||
|
||||
* test results: [test_results.md](https://github.com/kissjs/node-mongoskin/blob/master/test_results.md)
|
||||
* jscoverage: [**89%**](http://fengmk2.github.com/coverage/mongoskin.html)
|
||||
|
||||
## Test pass [mongodb] versions
|
||||
|
||||
* <del>>= 0.9.8 < 1.0.0</del>: mongodb have bug, it will throw a `TypeError: object is not a function`
|
||||
when connection open error.
|
||||
* 1.0.x
|
||||
* 1.1.x
|
||||
|
||||
```bash
|
||||
$ make test-version
|
||||
```
|
||||
|
||||
<a name='index'>
|
||||
|
||||
@@ -80,7 +94,9 @@ If you need validation, you can use [node-iform](https://github.com/guileen/node
|
||||
Install
|
||||
========
|
||||
|
||||
npm install mongoskin
|
||||
```bash
|
||||
$ npm install mongoskin
|
||||
```
|
||||
|
||||
[Back to index](#index)
|
||||
|
||||
@@ -101,10 +117,12 @@ Connect easier
|
||||
--------
|
||||
You can connect to mongodb easier now.
|
||||
|
||||
var mongo = require('mongoskin');
|
||||
mongo.db('localhost:27017/testdb').collection('blog').find().toArray(function(err, items){
|
||||
console.dir(items);
|
||||
})
|
||||
```js
|
||||
var mongo = require('mongoskin');
|
||||
mongo.db('localhost:27017/testdb').collection('blog').find().toArray(function (err, items) {
|
||||
console.dir(items);
|
||||
})
|
||||
```
|
||||
|
||||
<a name='quickstart-2'></a>
|
||||
|
||||
@@ -113,8 +131,10 @@ Server options and BSON options
|
||||
You can also set `auto_reconnect` options querystring.
|
||||
And native_parser options will automatically set if native_parser is avariable.
|
||||
|
||||
var mongo = require('mongoskin'),
|
||||
db = mongo.db('localhost:27017/test?auto_reconnect');
|
||||
```js
|
||||
var mongo = require('mongoskin');
|
||||
var db = mongo.db('localhost:27017/test?auto_reconnect');
|
||||
```
|
||||
|
||||
<a name='quickstart-3'></a>
|
||||
|
||||
@@ -122,21 +142,25 @@ Similar API with node-mongodb-native
|
||||
--------
|
||||
You can do everything that node-mongodb-native can do.
|
||||
|
||||
db.createCollection(...);
|
||||
db.collection('user').ensureIndex([['username', 1]], true, function(err, replies){});
|
||||
db.collection('posts').hint = 'slug';
|
||||
db.collection('posts').findOne({slug: 'whats-up'}, function(err, post){
|
||||
// do something
|
||||
});
|
||||
```js
|
||||
db.createCollection(...);
|
||||
db.collection('user').ensureIndex([['username', 1]], true, function (err, replies) {});
|
||||
db.collection('posts').hint = 'slug';
|
||||
db.collection('posts').findOne({slug: 'whats-up'}, function (err, post) {
|
||||
// do something
|
||||
});
|
||||
```
|
||||
|
||||
<a name='quickstart-4'></a>
|
||||
|
||||
Cursor easier
|
||||
--------
|
||||
|
||||
db.collection('posts').find().toArray(function(err, posts){
|
||||
// do something
|
||||
});
|
||||
```js
|
||||
db.collection('posts').find().toArray(function (err, posts) {
|
||||
// do something
|
||||
});
|
||||
```
|
||||
|
||||
<a name='quickstart-5'></a>
|
||||
|
||||
@@ -148,28 +172,30 @@ It is very useful if you want to use MVC patterns with nodejs and mongodb.
|
||||
You can also invoke collection by properties after bind,
|
||||
it could simplfy your `require`.
|
||||
|
||||
db.bind('posts', {
|
||||
findTop10 : function(fn){
|
||||
this.find({}, {limit:10, sort:[['views', -1]]}).toArray(fn);
|
||||
},
|
||||
removeTagWith : function(tag, fn){
|
||||
this.remove({tags:tag},fn);
|
||||
}
|
||||
});
|
||||
```js
|
||||
db.bind('posts', {
|
||||
findTop10 : function (fn) {
|
||||
this.find({}, {limit:10, sort:[['views', -1]]}).toArray(fn);
|
||||
},
|
||||
removeTagWith : function (tag, fn) {
|
||||
this.remove({tags:tag},fn);
|
||||
}
|
||||
});
|
||||
|
||||
db.bind('comments');
|
||||
db.bind('comments');
|
||||
|
||||
db.collection('posts').removeTagWith('delete', function(err, replies){
|
||||
//do something
|
||||
});
|
||||
db.collection('posts').removeTagWith('delete', function (err, replies) {
|
||||
//do something
|
||||
});
|
||||
|
||||
db.posts.findTop10(function(err, topPosts){
|
||||
//do something
|
||||
});
|
||||
db.posts.findTop10(function (err, topPosts) {
|
||||
//do something
|
||||
});
|
||||
|
||||
db.comments.find().toArray(function(err, comments){
|
||||
//do something
|
||||
});
|
||||
db.comments.find().toArray(function (err, comments) {
|
||||
//do something
|
||||
});
|
||||
```
|
||||
|
||||
[Back to index](#index)
|
||||
|
||||
@@ -191,47 +217,62 @@ Module
|
||||
|
||||
### MongoSkin Url format
|
||||
|
||||
[*://][username:password@]host[:port][/database][?auto_reconnect[=true|false]]`
|
||||
```
|
||||
[*://][username:password@]host[:port][/database][?auto_reconnect[=true|false]]`
|
||||
```
|
||||
|
||||
e.g.
|
||||
|
||||
localhost/blog
|
||||
mongo://admin:pass@127.0.0.1:27017/blog?auto_reconnect
|
||||
127.0.0.1?auto_reconnect=false
|
||||
```
|
||||
localhost/blog
|
||||
mongo://admin:pass@127.0.0.1:27017/blog?auto_reconnect
|
||||
127.0.0.1?auto_reconnect=false
|
||||
```
|
||||
|
||||
### db(databaseUrl, db_options)
|
||||
### db(serverURL[s], dbOptions, replicasetOptions)
|
||||
|
||||
Get or create instance of [SkinDb](#skindb).
|
||||
|
||||
var db = mongoskin.db('localhost:27017/testdb?auto_reconnect=true&poolSize=5');
|
||||
```js
|
||||
var db = mongoskin.db('localhost:27017/testdb?auto_reconnect=true&poolSize=5');
|
||||
```
|
||||
|
||||
for ReplSet server
|
||||
|
||||
var db = mongoskin.db(['192.168.0.1:27017/?auto_reconnect=true',
|
||||
'192.168.0.2:27017/?auto_reconnect=true',
|
||||
'192.168.0.3:27017/?auto_reconnect=true'],
|
||||
{
|
||||
database: 'testdb',
|
||||
retryMiliSeconds: 2000
|
||||
})
|
||||
```js
|
||||
var db = mongoskin.db([
|
||||
'192.168.0.1:27017/?auto_reconnect=true',
|
||||
'192.168.0.2:27017/?auto_reconnect=true',
|
||||
'192.168.0.3:27017/?auto_reconnect=true'
|
||||
], {
|
||||
database: 'testdb'
|
||||
}, {
|
||||
connectArbiter: false,
|
||||
socketOptions: {
|
||||
timeout: 2000
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### router(select)
|
||||
|
||||
select is function(collectionName) returns a database instance, means router collectionName to that database.
|
||||
select is `function(collectionName)` returns a database instance, means router collectionName to that database.
|
||||
|
||||
var db = mongo.router(function(coll_name){
|
||||
switch(coll_name) {
|
||||
case 'user':
|
||||
case 'message':
|
||||
return mongo.db('192.168.1.3/auth_db');
|
||||
default:
|
||||
return mongo.db('192.168.1.2/app_db');
|
||||
}
|
||||
});
|
||||
db.bind('user', require('./shared-user-methods'));
|
||||
var users = db.user; //auth_db.user
|
||||
var messages = db.collection('message'); // auth_db.message
|
||||
var products = db.collection('product'); //app_db.product
|
||||
```js
|
||||
var db = mongo.router(function (coll_name) {
|
||||
switch(coll_name) {
|
||||
case 'user':
|
||||
case 'message':
|
||||
return mongo.db('192.168.1.3/auth_db');
|
||||
default:
|
||||
return mongo.db('192.168.1.2/app_db');
|
||||
}
|
||||
});
|
||||
db.bind('user', require('./shared-user-methods'));
|
||||
var users = db.user; //auth_db.user
|
||||
var messages = db.collection('message'); // auth_db.message
|
||||
var products = db.collection('product'); //app_db.product
|
||||
```
|
||||
|
||||
### classes extends frome node-mongodb-native
|
||||
|
||||
@@ -323,12 +364,14 @@ db.collection(name) method.
|
||||
|
||||
e.g.
|
||||
|
||||
db.bind('book', {
|
||||
firstBook: function(fn){
|
||||
this.findOne(fn);
|
||||
}
|
||||
});
|
||||
db.book.firstBook(function(err, book){});
|
||||
```js
|
||||
db.bind('book', {
|
||||
firstBook: function (fn) {
|
||||
this.findOne(fn);
|
||||
}
|
||||
});
|
||||
db.book.firstBook(function (err, book) {});
|
||||
```
|
||||
|
||||
### all the methods from Db.prototype
|
||||
|
||||
@@ -354,7 +397,9 @@ instance, callback is function(err, collection).
|
||||
|
||||
Equivalent to
|
||||
|
||||
db.bson_serializer.ObjectID.createFromHexString(hex);
|
||||
```js
|
||||
db.bson_serializer.ObjectID.createFromHexString(hex);
|
||||
```
|
||||
|
||||
See [ObjectID.createFromHexString](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/bson/bson.js#L548)
|
||||
|
||||
@@ -363,20 +408,24 @@ See [ObjectID.createFromHexString](https://github.com/christkv/node-mongodb-nati
|
||||
|
||||
### Collection operation
|
||||
|
||||
checkCollectionName(collectionName)
|
||||
options(callback)
|
||||
rename(collectionName, callback)
|
||||
drop(callback)
|
||||
```js
|
||||
checkCollectionName(collectionName)
|
||||
options(callback)
|
||||
rename(collectionName, callback)
|
||||
drop(callback)
|
||||
```
|
||||
|
||||
<a name='inherit-indexes'>
|
||||
|
||||
### Indexes
|
||||
|
||||
createIndex (fieldOrSpec, unique, callback)
|
||||
ensureIndex (fieldOrSpec, unique, callback)
|
||||
indexInformation (callback)
|
||||
dropIndex (indexName, callback)
|
||||
dropIndexes (callback)
|
||||
```js
|
||||
createIndex(fieldOrSpec, unique, callback)
|
||||
ensureIndex(fieldOrSpec, unique, callback)
|
||||
indexInformation(callback)
|
||||
dropIndex(indexName, callback)
|
||||
dropIndexes(callback)
|
||||
```
|
||||
|
||||
See [mongodb-native indexes](https://github.com/christkv/node-mongodb-native/blob/master/docs/indexes.md)
|
||||
|
||||
@@ -390,9 +439,11 @@ See [mongodb-native queries](https://github.com/christkv/node-mongodb-native/blo
|
||||
|
||||
Equivalent to
|
||||
|
||||
collection.find(..., function(err, cursor){
|
||||
cursor.toArray(callback);
|
||||
});
|
||||
```js
|
||||
collection.find(..., function (err, cursor) {
|
||||
cursor.toArray(callback);
|
||||
});
|
||||
```
|
||||
|
||||
See [Collection.find](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L348)
|
||||
|
||||
@@ -400,9 +451,11 @@ See [Collection.find](https://github.com/christkv/node-mongodb-native/blob/maste
|
||||
|
||||
Equivalent to
|
||||
|
||||
collection.find(..., function(err, cursor){
|
||||
cursor.each(callback);
|
||||
});
|
||||
```js
|
||||
collection.find(..., function (err, cursor) {
|
||||
cursor.each(callback);
|
||||
});
|
||||
```
|
||||
|
||||
See [Collection.find](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L348)
|
||||
|
||||
@@ -410,7 +463,9 @@ See [Collection.find](https://github.com/christkv/node-mongodb-native/blob/maste
|
||||
|
||||
Equivalent to
|
||||
|
||||
collection.findOne({_id, ObjectID.createFromHexString(id)}, ..., callback);
|
||||
```js
|
||||
collection.findOne({_id, ObjectID.createFromHexString(id)}, ..., callback);
|
||||
```
|
||||
|
||||
See [Collection.findOne](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L417)
|
||||
|
||||
@@ -422,44 +477,48 @@ method, else it will return a future [SkinCursor](#skincursor).
|
||||
|
||||
e.g.
|
||||
|
||||
// callback
|
||||
db.book.find({}, function(err, cursor){/* do something */});
|
||||
// future SkinCursor
|
||||
db.book.find().toArray(function(err, books){/* do something */});
|
||||
|
||||
|
||||
```js
|
||||
// callback
|
||||
db.book.find({}, function (err, cursor) {/* do something */});
|
||||
// future SkinCursor
|
||||
db.book.find().toArray(function (err, books) {/* do something */});
|
||||
```
|
||||
|
||||
#### normalizeHintField(hint)
|
||||
|
||||
#### find
|
||||
|
||||
/**
|
||||
* Various argument possibilities
|
||||
* 1 callback
|
||||
* 2 selector, callback,
|
||||
* 2 callback, options // really?!
|
||||
* 3 selector, fields, callback
|
||||
* 3 selector, options, callback
|
||||
* 4,selector, fields, options, callback
|
||||
* 5 selector, fields, skip, limit, callback
|
||||
* 6 selector, fields, skip, limit, timeout, callback
|
||||
*
|
||||
* Available options:
|
||||
* limit, sort, fields, skip, hint, explain, snapshot, timeout, tailable, batchSize
|
||||
*/
|
||||
```js
|
||||
/**
|
||||
* Various argument possibilities
|
||||
* 1 callback
|
||||
* 2 selector, callback,
|
||||
* 2 callback, options // really?!
|
||||
* 3 selector, fields, callback
|
||||
* 3 selector, options, callback
|
||||
* 4,selector, fields, options, callback
|
||||
* 5 selector, fields, skip, limit, callback
|
||||
* 6 selector, fields, skip, limit, timeout, callback
|
||||
*
|
||||
* Available options:
|
||||
* limit, sort, fields, skip, hint, explain, snapshot, timeout, tailable, batchSize
|
||||
*/
|
||||
```
|
||||
|
||||
#### findAndModify(query, sort, update, options, callback)
|
||||
|
||||
/**
|
||||
Fetch and update a collection
|
||||
query: a filter for the query
|
||||
sort: if multiple docs match, choose the first one in the specified sort order as the object to manipulate
|
||||
update: an object describing the modifications to the documents selected by the query
|
||||
options:
|
||||
remove: set to a true to remove the object before returning
|
||||
new: set to true if you want to return the modified object rather than the original. Ignored for remove.
|
||||
upsert: true/false (perform upsert operation)
|
||||
**/
|
||||
```js
|
||||
/**
|
||||
Fetch and update a collection
|
||||
query: a filter for the query
|
||||
sort: if multiple docs match, choose the first one in the specified sort order as the object to manipulate
|
||||
update: an object describing the modifications to the documents selected by the query
|
||||
options:
|
||||
remove: set to a true to remove the object before returning
|
||||
new: set to true if you want to return the modified object rather than the original. Ignored for remove.
|
||||
upsert: true/false (perform upsert operation)
|
||||
**/
|
||||
```
|
||||
|
||||
#### findOne(queryObject, options, callback)
|
||||
|
||||
@@ -469,30 +528,37 @@ e.g.
|
||||
|
||||
#### mapReduce(map, reduce, options, callback)
|
||||
|
||||
e.g. ```
|
||||
var map = function(){
|
||||
emit(test(this.timestamp.getYear()), 1);
|
||||
}
|
||||
|
||||
var reduce = function(k, v){
|
||||
count = 0;
|
||||
for(i = 0; i < v.length; i++) {
|
||||
count += v[i];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
collection.mapReduce(map, reduce, {scope:{test:new client.bson_serializer.Code(t.toString())}}, function(err, collection) {
|
||||
collection.find(function(err, cursor) {
|
||||
cursor.toArray(function(err, results) {
|
||||
test.equal(2, results[0].value)
|
||||
finished_test({test_map_reduce_functions_scope:'ok'});
|
||||
})
|
||||
})
|
||||
```
|
||||
e.g.
|
||||
|
||||
```js
|
||||
var map = function () {
|
||||
emit(test(this.timestamp.getYear()), 1);
|
||||
}
|
||||
|
||||
var reduce = function (k, v){
|
||||
count = 0;
|
||||
for (i = 0; i < v.length; i++) {
|
||||
count += v[i];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
var options = {scope: {test: new client.bson_serializer.Code(t.toString())}};
|
||||
collection.mapReduce(map, reduce, options, function (err, collection) {
|
||||
collection.find(function (err, cursor) {
|
||||
cursor.toArray(function (err, results) {
|
||||
test.equal(2, results[0].value)
|
||||
finished_test({test_map_reduce_functions_scope:'ok'});
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
#### group(keys, condition, initial, reduce, command, callback)
|
||||
|
||||
e.g. `collection.group([], {}, {"count":0}, "function (obj, prev) { prev.count++; }", true, function(err, results) {`
|
||||
e.g.
|
||||
|
||||
```js
|
||||
collection.group([], {}, {"count":0}, "function (obj, prev) { prev.count++; }", true, function(err, results) {});
|
||||
```
|
||||
|
||||
#### count(query, callback)
|
||||
#### distinct(key, query, callback)
|
||||
@@ -509,19 +575,21 @@ e.g.
|
||||
|
||||
#### save(doc, options, callback)
|
||||
|
||||
/**
|
||||
Update a single document in this collection.
|
||||
spec - a associcated array containing the fields that need to be present in
|
||||
the document for the update to succeed
|
||||
```js
|
||||
/**
|
||||
Update a single document in this collection.
|
||||
spec - a associcated array containing the fields that need to be present in
|
||||
the document for the update to succeed
|
||||
|
||||
document - an associated array with the fields to be updated or in the case of
|
||||
a upsert operation the fields to be inserted.
|
||||
document - an associated array with the fields to be updated or in the case of
|
||||
a upsert operation the fields to be inserted.
|
||||
|
||||
Options:
|
||||
upsert - true/false (perform upsert operation)
|
||||
multi - true/false (update all documents matching spec)
|
||||
safe - true/false (perform check if the operation failed, required extra call to db)
|
||||
**/
|
||||
Options:
|
||||
upsert - true/false (perform upsert operation)
|
||||
multi - true/false (update all documents matching spec)
|
||||
safe - true/false (perform check if the operation failed, required extra call to db)
|
||||
**/
|
||||
```
|
||||
|
||||
#### update(spec, document, options, callback)
|
||||
|
||||
@@ -529,11 +597,12 @@ e.g.
|
||||
|
||||
Equivalent to
|
||||
|
||||
collection.update({_id, ObjectID.createFromHexString(id)}, ..., callback);
|
||||
```js
|
||||
collection.update({_id, ObjectID.createFromHexString(id)}, ..., callback);
|
||||
```
|
||||
|
||||
See [Collection.update](https://github.com/christkv/node-mongodb-native/blob/master/docs/insert.md)
|
||||
|
||||
|
||||
<a name='inherit-removing'>
|
||||
|
||||
### Removing
|
||||
@@ -554,17 +623,76 @@ of node-mongodb-native for more information.
|
||||
|
||||
All these methods will return the SkinCursor itself.
|
||||
|
||||
sort(keyOrList, [direction], [callback])
|
||||
limit(limit, [callback])
|
||||
skip(skip, [callback])
|
||||
batchSize(skip, [callback])
|
||||
|
||||
toArray(callback)
|
||||
each(callback)
|
||||
count(callback)
|
||||
nextObject(callback)
|
||||
getMore(callback)
|
||||
explain(callback)
|
||||
```js
|
||||
sort(keyOrList, [direction], [callback])
|
||||
limit(limit, [callback])
|
||||
skip(skip, [callback])
|
||||
batchSize(skip, [callback])
|
||||
|
||||
toArray(callback)
|
||||
each(callback)
|
||||
count(callback)
|
||||
nextObject(callback)
|
||||
getMore(callback)
|
||||
explain(callback)
|
||||
```
|
||||
|
||||
[Back to index](#index)
|
||||
|
||||
## How to validate input?
|
||||
|
||||
I wrote a middleware to validate post data, [node-iform](https://github.com/guileen/node-iform)
|
||||
base on [node-validator](https://github.com/chriso/node-validator)
|
||||
|
||||
## Authors
|
||||
|
||||
Below is the output from `git-summary`.
|
||||
|
||||
```
|
||||
project: node-mongoskin
|
||||
commits: 112
|
||||
active : 54 days
|
||||
files : 39
|
||||
authors:
|
||||
49 Lin Gui 43.8%
|
||||
34 guilin 桂林 30.4%
|
||||
9 fengmk2 8.0%
|
||||
5 guilin 4.5%
|
||||
2 François de Metz 1.8%
|
||||
2 Paul Gebheim 1.8%
|
||||
2 Gui Lin 1.8%
|
||||
1 humanchimp 0.9%
|
||||
1 Aneil Mallavarapu 0.9%
|
||||
1 wmertens 0.9%
|
||||
1 Harvey McQueen 0.9%
|
||||
1 Joe Faber 0.9%
|
||||
1 Matt Perpick 0.9%
|
||||
1 Quang Van 0.9%
|
||||
1 Rakshit Menpara 0.9%
|
||||
1 Wout Mertens 0.9%
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2011 - 2012 kissjs.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Reference in New Issue
Block a user