3
0
mirror of https://github.com/reality/dbot.git synced 2025-08-02 00:37:25 +02:00

Compare commits

...

1362 Commits

Author SHA1 Message Date
reality
a77c6296f1 rmconfig and small changes 2021-12-22 17:04:34 +00:00
reality
2307f164f8
Update js.js 2021-09-22 12:57:41 +01:00
reality
7d9a9eeeff
Merge pull request #690 from yoisahb5/js-vm2
Use vm2 instead of sandbox library
2021-09-22 12:53:33 +01:00
yoisahb5
0ac81b886e Use vm2 instead of sandbox library 2021-08-08 15:27:05 +02:00
reality
77a9c346d8
Merge pull request #688 from powerjungle/master
Add new clear tells command
2021-03-15 13:53:05 +00:00
powerjungle
97ebd371bf
Add new clear tells command 2021-03-10 15:05:39 +01:00
reality
ec3d6ed13b
Merge pull request #687 from powerjungle/master
Add README.md to tell module
2021-02-28 14:24:15 +00:00
powerjungle
a245d385f7
Add README.md to tell module 2021-02-28 13:51:47 +01:00
Luke Slater
695398d8fb
Merge pull request #682 from Scritches/master
Initial commit of new todo list module
2019-04-24 22:46:53 +01:00
Scritches
08922c8e67 Initial commit of new todo list module 2018-11-02 16:21:51 -04:00
Luke Slater
dfdb31b31d
Merge pull request #680 from Scritches/master
Improved error messages for LastFM module.
2018-09-02 11:54:02 +01:00
Scritches
1b18c9f048 Improved error messages for LastFM module. 2018-09-01 22:21:55 -04:00
Luke Slater
8c97c665a6
Merge pull request #679 from Scritches/master
Urban dictionary API changed - removed result_type
2018-08-27 19:26:50 +01:00
Scritches
1657e7cc02 Urban dictionary API changed - removed result_type 2018-08-26 18:08:01 -04:00
Luke Slater
09f8f525e6
time is literally the stupidest thing there is 2018-06-06 23:20:39 +01:00
reality
d64375ca50 sasl hint 2018-05-28 14:35:11 +00:00
reality
a4697e8d36 Merge branch 'master' of https://github.com/reality/dbot 2018-05-20 21:46:26 +00:00
reality
a97bda3c20 HA 2018-05-20 21:46:19 +00:00
Luke Slater
ab6cb80ea2
Merge pull request #677 from Scritches/master
'kick' and 'kill_namespam' module changes
2018-05-16 10:34:38 +01:00
Scritches
c26be5410f
Merge branch 'master' into master 2018-05-15 20:12:40 -04:00
Scritches
e11abe5af4 kills are deferred until user joins a non-exempt channel 2018-05-15 20:09:43 -04:00
Luke Slater
6a255244df
fix save callback lack (lol) 2018-05-12 18:56:14 +01:00
Scritches
f3dcc0e693 ~nban no longer adds redundant +b if user was killed 2018-05-05 13:45:54 -04:00
Scritches
ed69582c7a 4-indent to 2-indent 2018-05-05 13:35:49 -04:00
Luke Slater
814a84ee8e
Merge pull request #676 from Scritches/master
Various module fixes / improvements
2018-05-05 16:34:04 +01:00
Scritches
a5f9998872 Added ~sp as alias to ~spotify 2018-05-01 16:58:52 -04:00
Scritches
d544dcf017 clikill spares SASL-authenticated users from match kills 2018-05-01 16:47:25 -04:00
Scritches
bbfc4c18a6 xkcd title / relevent text search feature done right. 2018-04-26 19:12:20 -04:00
Scritches
0c8c377b08 ~xkcd command now finds relevant XKCDs when given text instead of a number 2018-04-26 17:14:18 -04:00
Scritches
c298813b28 Adds OMDB module to replace the RottenTomatoes module.
~movie command replaces ~rt command. API key from http://www.omdbapi.com/apikey.aspx
2018-04-26 16:58:15 -04:00
Scritches
0f0877f27a Fixed YouTube video duration reporting 2018-04-26 16:50:21 -04:00
reality
554a9e995b do not fail broken regex 2018-04-20 21:01:11 +00:00
Luke Slater
ae989d60ae
Merge pull request #675 from Scritches/master
Adds a module that queries the Online Encyclopedia of Integer Sequences
2018-04-19 21:50:58 +01:00
Scritches
f7b83e98b7 support for random sequences 2018-04-18 00:50:22 -04:00
Scritches
b415ee086f Add OEIS module
## Queries the **Online Encyclopedia of Integer Sequences** for interesting number sequences.

#### Sequence by example:
```
~sequence 1 2 3 4 5
```

#### Sequence by ID number
```
~sequence a27
```

#### Sequence by keywords
```
~sequence positive integers
```

In all cases the following is returned:
```
[oeis] A000027: "The positive integers." - (1, 2, 3, 4, 5, 6, 7, 8, ...) https://oeis.org/A000027
```
2018-04-18 00:26:05 -04:00
Luke Slater
944827c4d9
Merge pull request #674 from Scritches/master
Bunch of little fixes and style updates
2018-04-14 20:14:57 +01:00
Scritches
97642f35a9 Got rid of all the const
But muh self-documenting code :'(
2018-04-14 15:07:26 -04:00
Scritches
2d20f19572 Fix for lingering votequiets 2018-04-14 14:54:23 -04:00
Luke Slater
98c8894f95
Merge pull request #673 from Scritches/master
Initial rewrite of goodreads module using async/await
2018-04-14 19:51:57 +01:00
Scritches
11a7f1d20e Fix ~lastfm registered date display 2018-04-14 14:01:36 -04:00
Scritches
86d0a6f31b Link module title regexp fix
Fix for sites that use <\/title> instead of </title> to close their title elements.
2018-04-14 13:38:28 -04:00
Scritches
71c2c52d47 Initial rewrite of goodreads module using async/await
Covers original functionality plus adds a new ~reading command.

There is probably a lot of duplication in the module itself that can be cleaned up with some additional metaprogramming but *eh* I'm tired tonight.
2018-04-12 01:11:15 -04:00
Luke Slater
fbc4ac5afe
Merge pull request #672 from Scritches/master
Some more music module fixes
2018-04-11 14:46:23 +01:00
Scritches
a574b7d2ed more reasonable ~define
Tell wordnik to use the canonical version of the word where available (to avoid responses like "the plural of 'cat'" when doing "~define cats" - just tell me what cats are dammit)
2018-04-10 16:06:38 -04:00
Scritches
93ee3cb08b lastfm and spotify fixes
### lastfm module

removed ~taste and taste compare functions from lastfm - their API no longer supports these calls

Improved error reporting for ~suggestion and also parallelized the youtube/spotify queries

### spotify module

removed link matching - the Link module provides the exact same information as directly querying spotify so there's no real point
2018-04-10 15:35:57 -04:00
Scritches
597171c37d set last link in channel when ~yt command is used 2018-04-10 13:30:20 -04:00
Luke Slater
8182980420
Merge pull request #671 from Scritches/master
Words module api support for phrases
2018-03-30 17:24:30 +01:00
Scritches
bb28cebde1 Words module api support for phrases
~define, ~example, and ~like now all support phrases.
2018-03-30 12:22:03 -04:00
Luke Slater
48728c5801
Merge pull request #670 from Scritches/master
New minify module
2018-03-28 21:52:55 +01:00
Scritches
43cfe3b637 Minify module
basic framework for more human-readable error responses from the bitly minifier
2018-03-26 16:23:03 -04:00
Scritches
19cc4c474d New minify module
Added a module that provides URL minifier support for dbot.

Updated spotify and lastfm modules with support for url minimization via the include 'bitly' minimizer (which minimizes spotify.com links to spoti.fi - very nice)
2018-03-26 13:52:06 -04:00
Luke Slater
f5c9a275a9
Merge pull request #669 from Scritches/master
Bunch of spotify, youtube, and lastfm improvements
2018-03-25 03:28:22 +01:00
Scritches
ff7be1f31d https instead of http for ~listening youtube link 2018-03-24 22:10:57 -04:00
Scritches
0118f962b6 Include spotify desktop URI in ~syt results 2018-03-24 21:11:46 -04:00
Scritches
167525b5b9 Added ~ytpl command to search youtube for playlists 2018-03-24 20:57:57 -04:00
Scritches
25d572e8cb lastfm ~listening: make youtube and spotify api calls in parallel 2018-03-24 19:24:57 -04:00
Scritches
72a4552742 Revert "test"
This reverts commit bd148915ed0bb814971e8031cef5b5312502500c.
2018-03-24 17:22:22 -04:00
Scritches
bd148915ed test 2018-03-24 17:21:26 -04:00
Scritches
354c0935b9 Move spotify api key into config; Restore spotify functionality to lastfm module ~listening command 2018-03-24 16:20:33 -04:00
Luke Slater
4a4e41b702
Merge pull request #668 from Scritches/master
Added padding around the urls in the output
2018-03-24 01:42:18 +00:00
Scritches
b87175e665 Added padding around the urls in the output 2018-03-23 21:37:43 -04:00
Luke Slater
9a7e1ab4bf
Merge pull request #666 from Scritches/master
fixed tabs/spaces and added spotify uri for desktop app linkability
2018-03-22 11:03:55 +00:00
Scritches
10c642c94f fixed tabs/spaces and added spotify uri for desktop app linkability 2018-03-22 03:04:14 -04:00
Luke Slater
dde0200032
Merge pull request #665 from Scritches/master
Added support for the minified youtube links returned by the ~yt command to the ~syt command
2018-03-08 21:25:03 +00:00
Scritches
217e65df96 Added necessary authentication for spotify API calls and fixed youtube link regex. 2018-03-08 16:11:12 -05:00
Scritches
03067f97d6 Added support for the minified youtube links returned by the ~yt command 2018-03-07 17:30:35 -05:00
reality
00215f62f0 that should learn it 2018-03-01 14:21:09 +00:00
reality
9a4a86c6ba weird config 2018-03-01 14:15:35 +00:00
reality
7d31560458 clean 2018-03-01 14:01:00 +00:00
reality
f55f645a3b some smal fixes and clarities 2018-03-01 13:57:45 +00:00
reality
7debad9a1d oopsie 2018-03-01 13:53:02 +00:00
reality
9faffa0d11 add cliconn autorek 2018-03-01 13:41:59 +00:00
reality
3c22b811ad clean up the bug with fresh whowas lookup 2018-02-28 17:42:08 +00:00
reality
329836d577 Merge branch 'master' of https://github.com/reality/dbot 2018-02-28 17:39:31 +00:00
reality
5796308e62 fix temp unban 2018-02-28 17:39:21 +00:00
Luke Slater
3972b5272b
the start of yo callback ain't a valid host 2018-02-24 00:56:26 +00:00
reality
17ecf62da0 finish alsuti 2018-02-23 14:03:16 +00:00
reality
9b55509257 alsuti sustatus 2018-02-23 13:47:23 +00:00
reality
69c06537e2 sustatus alsuti 2018-02-23 12:30:18 +00:00
reality
8fe032579d prevent multiple yes votes by using votequiet fallback (lol) 2018-02-22 18:28:10 +00:00
reality
fe8168a237 whowas works correctly as fallback for host lookup 2018-02-22 17:45:04 +00:00
reality
016c132158 start fix whowas 2018-02-22 17:30:15 +00:00
reality
9df86cdd99 ability to pass host manually to nunban, and extra info about host in notifies 2018-02-22 16:01:40 +00:00
reality
00ac08a9da autoquiet at 4 on votequiet, increase period to 1.5 mins 2018-02-17 18:41:04 +00:00
reality
eba4a9a4a1 votequiet on already polled user adds yes vote 2018-02-17 18:06:30 +00:00
reality
beaa420015 i am not very smart 2018-02-16 14:36:56 +00:00
reality
709cd085a9 add content kills 2018-02-16 14:29:17 +00:00
reality
56d12bd649 also add check for distinctive spam content 2018-02-16 14:22:16 +00:00
reality
510a02d08a exempt 2018-02-16 13:44:47 +00:00
reality
d7f212ea52 haha check out the bug there, that is actually really funny 2018-02-16 13:37:26 +00:00
reality
3b6dd18611 more syntax 2018-02-16 13:30:56 +00:00
reality
58256a8f62 appleg 2018-02-16 13:29:04 +00:00
reality
0da6af229f syntax! 2018-02-16 13:19:12 +00:00
reality
8310dc38ff module to deal with ppl hilighting lots of ppl at once. bad 2018-02-16 13:17:52 +00:00
reality
ebb0a023c0 more appropriate note string 2018-02-10 12:59:02 +00:00
reality
f097685c3d notes fixes 2018-02-10 12:47:54 +00:00
reality
4f269a5c02 wtf was that there for? 2018-02-10 12:40:27 +00:00
Luke Slater
777d738394 new notes functionality 2018-02-10 12:35:31 +00:00
reality
e62a1c8484 external lpmcount 2017-11-02 18:22:05 +00:00
krn
0f1c6c6782 Merge pull request #664 from somehibs/master
install script uses command -v for executable detection
2017-07-31 18:17:01 +01:00
alex
b8bbaab9d9 install script uses command -v for executable detection 2017-07-22 03:56:17 +01:00
reality
3204c422bb fixes 2017-07-18 19:03:00 +00:00
reality
ec86b6e1a8 fix indentation and stuff 2017-07-18 14:56:01 +00:00
reality
07156b2eb3 this 2017-07-18 14:32:42 +00:00
reality
d37326c88e fix all ban 2017-07-18 14:28:42 +00:00
reality
1f0e13bd2a new jsbot 2017-07-18 13:19:23 +00:00
reality
0d233f69b7 fix for nick tracking wrt new jsbot 2017-07-18 03:11:18 +00:00
reality
e22133d685 fix ignore 2017-07-18 02:52:59 +00:00
reality
0d2d00635c fixes 2017-07-18 02:51:45 +00:00
reality
d41836e937 index for aliases 2017-07-18 02:16:07 +00:00
reality
c1c54bbd59 fixes 2017-07-11 14:36:14 +00:00
reality
6a38eb5289 update with fixes 2017-07-11 14:22:18 +00:00
reality
d25ec221c7 fix for new jsbot 2017-07-11 14:21:59 +00:00
reality
54efa27ff2 update jsbot 2017-07-11 12:44:38 +00:00
reality
f02d2b74df curse you spotify 2017-06-05 17:29:12 +00:00
reality
330868686d oops 2017-03-25 00:43:31 +00:00
reality
9a44c41fbd qsearch random quote 2017-03-25 00:40:52 +00:00
reality
92598b13c2 channel with log 2016-12-14 22:09:19 +00:00
reality
a57b123fed two space indent for log and karma, karma logging 2016-12-14 21:58:42 +00:00
reality
ef86954025 fix for new web api 2016-12-05 20:04:37 +00:00
reality
7964bb9e88 spotify link in listening out 2016-12-05 19:48:08 +00:00
rlty
238c112986 Merge pull request #658 from speeddefrost/master
Fix broken regex. Misc cleanup. Add some brackets.
2016-10-17 06:53:48 +00:00
speeddefrost
d4d101bc94 Fix broken regex. Misc cleanup. Add some brackets. 2016-10-16 23:43:16 -07:00
rlty
5191eca0a4 Merge pull request #654 from speeddefrost/master
Merge common time parameters for remind commands. - see code review for additional comments
2016-10-12 10:49:59 +00:00
speeddefrost
3f599ddfc2 Merge common time parameters for remind commands. 2016-10-04 05:49:38 -07:00
reality
0e95f8e42a cspeed 2016-06-21 08:22:49 +00:00
reality
485e08ff97 fix unban 2016-05-12 07:39:03 +00:00
reality
ed24043a55 fix ban 2016-05-12 07:38:18 +00:00
reality
e8f657de94 that should learn it 2016-05-07 16:29:18 +00:00
reality
aeea5a7e18 multiple udp clients 2016-05-07 16:04:10 +00:00
reality
2b043d018b remove console log 2016-04-24 00:16:53 +00:00
reality
45a27904bd changes 2016-04-24 00:14:54 +00:00
reality
cfbb71faa6 that should learn it? 2016-04-13 22:25:51 +00:00
reality
d9093e6da8 that should learn it? 2016-04-13 22:19:14 +00:00
reality
930607b4fe that should learn it? 2016-04-13 22:15:03 +00:00
reality
601d10b0de test reddit colour 2016-04-13 22:09:20 +00:00
reality
92c045d8c7 fix object object nonsense 2016-04-12 19:59:08 +00:00
reality
face69d31a underban 2016-04-11 22:01:59 +00:00
reality
45153a45d2 regex missing 2016-04-11 21:53:57 +00:00
reality
e767e43771 years 2016-04-11 21:51:45 +00:00
reality
2ebeea1ef4 test 2016-04-11 21:49:17 +00:00
reality
a58e1fcc4b new jsbot 2016-04-11 21:34:16 +00:00
reality
7f2878ce58 api function 2016-04-11 18:23:02 +00:00
reality
a5657a5a36 cached 2016-04-11 18:15:10 +00:00
reality
bab36d5af3 better geoip 2016-04-11 18:08:20 +00:00
reality
d19fc76088 new jsbot 2016-04-06 00:53:19 +00:00
reality
fc0fe6f5be fix 2016-03-31 22:00:55 +00:00
reality
45e44bc7f8 fix 2016-03-31 21:59:31 +00:00
reality
d442461076 no 2016-03-23 17:32:05 +00:00
reality
c47677a590 remove file 2016-03-23 15:43:47 +00:00
reality
f2c61c95b9 summary 2016-03-23 15:36:15 +00:00
reality
e120869bcd redirects 2016-03-22 23:03:46 +00:00
reality
a14d042be2 redirects 2016-03-22 22:56:29 +00:00
reality
bc114a10e6 redirects 2016-03-22 22:54:17 +00:00
reality
5e8ccb6bcc redirects 2016-03-22 22:47:21 +00:00
reality
b61c482a32 redirects 2016-03-22 22:30:06 +00:00
reality
ba2ad2649f working 2016-03-22 21:36:26 +00:00
reality
0473597b0a better ~lol 2016-03-22 21:31:59 +00:00
reality
04fb1cc67b add channel name 2016-03-20 17:51:48 +00:00
reality
72e6fca9e5 timeout 2016-03-20 17:48:07 +00:00
reality
71632f401b or is it that 2016-03-12 22:51:08 +00:00
reality
d31a95b3a3 wrong order for tetris scores 2016-03-12 22:30:37 +00:00
reality
fa431ac800 vitetris 2016-03-12 22:16:02 +00:00
reality
aed72f52dc fix flashy 2016-03-04 17:18:35 +00:00
reality
b9064302ba fix spaces 2016-03-03 17:41:17 +00:00
reality
40e20f06b0 ~w 2016-03-03 17:39:08 +00:00
reality
84f8e7a151 ~w 2016-03-03 17:36:21 +00:00
reality
86c570a8c8 ~wikipedia 2016-03-03 17:31:42 +00:00
reality
fd1a76d3bc translate module 2016-03-03 16:02:10 +00:00
reality
266f6b58f4 translate module 2016-03-03 15:55:47 +00:00
reality
212ae87e8b translate module 2016-03-03 15:52:29 +00:00
reality
6038443225 rookie mistake 2016-02-21 20:06:51 +00:00
rlty
8ce27053ce Merge pull request #652 from EddieCurtis/patch-3
Fixing url for m.links.alternate
2016-02-20 23:07:22 +00:00
Eddie Curtis
e2949094a2 Fixing url for m.links.alternate 2016-02-20 23:06:28 +00:00
reality
8095aea3d0 rookie mistake 2016-02-19 19:28:01 +00:00
reality
2f6dc6f25f rookie mistake 2016-02-19 19:24:01 +00:00
reality
d1b764d4ec rookie mistake 2016-02-19 19:18:43 +00:00
reality
badf17b0ec rookie mistake 2016-02-19 19:17:05 +00:00
reality
f4a203e416 rookie mistake 2016-02-19 19:15:06 +00:00
reality
d4c3edca0a ffs lol 2016-02-19 19:14:10 +00:00
reality
c26c776b48 oops 2016-02-19 19:13:32 +00:00
reality
c247f48fbe fff 2016-02-19 19:12:22 +00:00
reality
da8c297973 things 2016-02-19 18:59:22 +00:00
reality
8be0261295 things 2016-02-19 18:57:11 +00:00
reality
991411f28d thing 2016-02-19 18:55:43 +00:00
reality
c63c17d9d5 things 2016-02-16 17:39:10 +00:00
reality
4478f4e405 things 2016-02-16 17:37:09 +00:00
reality
660693281f things 2016-02-16 17:32:29 +00:00
reality
a4141288e5 batchstatus 2016-02-02 17:31:36 +00:00
reality
a107c81ad3 batchstatus 2016-02-02 15:03:57 +00:00
reality
ad448a51fa batchstatus 2016-02-02 15:00:34 +00:00
reality
affb89662f time thing 2016-01-29 22:33:58 +00:00
reality
2d2d00ccbf fix order 2016-01-29 22:19:35 +00:00
reality
da2ad191c9 fix ban count 2016-01-29 22:13:44 +00:00
reality
a52fdbcea5 i like colours 2016-01-29 18:05:12 +00:00
reality
c16f65c5b8 i like colours 2016-01-29 18:03:22 +00:00
reality
4afeb8ff38 sustatus thing 2016-01-29 17:58:04 +00:00
reality
431266136c sustatus thing 2016-01-29 17:56:38 +00:00
reality
e52699b211 sustatus thing 2016-01-29 17:55:03 +00:00
reality
9ca81e3094 fix regex 2016-01-28 18:41:44 +00:00
reality
c10b65ef3b various fixes to the reporting system and related stuff 2016-01-28 18:29:51 +00:00
reality
ac9488bad9 offlineReporting configurable 2016-01-28 17:36:19 +00:00
reality
3af2cbb678 remove url from warn 2016-01-26 16:57:23 +00:00
reality
8c06ec9dcf helpful output 2016-01-15 23:22:59 +00:00
reality
dc00730168 remind-like time periods for nban and quiet 2016-01-15 21:36:24 +00:00
reality
eb35db1074 oops 2015-12-09 20:11:33 +00:00
reality
890103e4ab oops 2015-12-09 19:00:39 +00:00
reality
eebf1d9680 tell 2015-12-09 18:53:32 +00:00
reality
44f46cfc75 yes 2015-11-17 18:52:49 +00:00
reality
5abb1ab166 who cares about floods 2015-10-27 19:38:10 +00:00
reality
92e4db287d oops 2015-10-27 19:36:51 +00:00
reality
a378ec7ab4 oops 2015-10-27 19:33:08 +00:00
reality
2ea263f997 oops 2015-10-27 19:30:32 +00:00
reality
d473d95e42 even quicker like 2015-10-27 19:26:58 +00:00
reality
339fb3ddfb ban from current channel first 2015-10-27 19:22:29 +00:00
reality
ef500e2d96 mesg 2015-10-20 18:59:55 +00:00
reality
04c411c6c1 mesg 2015-10-20 18:58:04 +00:00
reality
04d797c6d3 mesg 2015-10-20 18:56:00 +00:00
reality
b49b9b99c4 mesg 2015-10-20 18:30:15 +00:00
reality
e88f2a70b1 mesg 2015-10-20 18:29:05 +00:00
reality
2d0fa7fe59 name clash 2015-10-20 18:26:39 +00:00
reality
5b7c52a63f oops 2015-10-20 18:24:24 +00:00
reality
74377c1db7 dnsbl 2015-10-20 18:22:40 +00:00
reality
939797f5be ignore pms for stats 2015-10-13 05:36:49 +00:00
reality
3a57f11f69 ~myreminders 2015-10-08 18:07:50 +00:00
reality
bece1b245f ~random moved to ~randomdata 2015-08-19 19:11:33 +00:00
reality
2e3d4582f1 derp 2015-08-13 21:03:21 +00:00
reality
0069003cc7 scope 2015-08-13 21:02:14 +00:00
reality
c6d352038c run ncount on other users 2015-08-13 20:59:56 +00:00
reality
25d26b5586 quote interpolation recursion 2015-08-13 14:36:22 +00:00
reality
11a0a76a9d auth external 2015-07-24 01:02:21 +00:00
reality
1252ef39d1 add target to record 2015-07-23 09:58:31 +00:00
reality
bf54039724 oops 2015-07-22 23:24:40 +00:00
reality
b82a3e72ff properly resolve unbans 2015-07-22 23:21:56 +00:00
reality
d5b35a7b13 change the input for wolfram alpha command 2015-07-21 13:40:02 +00:00
reality
deae0ae352 ye 2015-07-20 15:21:56 +00:00
reality
8cd0b07c76 ? 2015-07-20 15:19:57 +00:00
reality
db25eadedf only post a radio update every 2 minutes 2015-07-20 15:13:01 +00:00
reality
bfa4de5a1a filesize in imgur 2015-07-19 21:34:09 +00:00
reality
cf509cb3c5 that was dumb 2015-07-19 17:03:18 +00:00
reality
5f8cbe3fb1 only save the db to disk every minute 2015-07-19 16:56:08 +00:00
reality
36496b64ac fix predo for quit 2015-07-19 00:15:31 +00:00
reality
7ce6cb5dc2 import moment 2015-07-17 23:39:19 +00:00
reality
5084722e0b import moment 2015-07-17 23:38:17 +00:00
reality
a3fd5e71f3 record daily last used [#650] 2015-07-17 23:37:24 +00:00
reality
fd0d3829d8 add time to ~concerning 2015-07-17 22:52:35 +00:00
reality
7fcd277815 ~rmlastwarning 2015-07-08 20:47:15 +00:00
reality
050fa88e47 working flag 2015-07-07 18:17:10 +00:00
reality
24aaf298f7 fix another potential race condition 2015-07-07 17:58:56 +00:00
reality
024ee7913e fix race condition in getting flag stack 2015-07-07 17:45:12 +00:00
reality
f7785c95a3 oops 2015-06-25 14:30:14 +00:00
reality
c584e7b8f5 tagging at the back@ too 2015-06-25 14:28:21 +00:00
reality
2483ec1ef6 idk 2015-05-29 17:26:04 +00:00
reality
aba5ac4fa5 oops 2015-05-06 18:20:25 +00:00
reality
4895c12b6d fix for nowplaying 2015-05-06 18:18:27 +00:00
reality
b28a5f6655 fix for nowplaying 2015-05-06 18:17:06 +00:00
reality
b440a232fc [Close #639] 2015-05-03 09:29:36 +00:00
reality
a9dff5c39e merge nicks 2015-05-01 07:58:36 +00:00
reality
10f853c921 fix for below one minite 2015-04-27 09:51:45 +00:00
reality
b9786b1d2f fix for below one minite 2015-04-27 09:50:51 +00:00
reality
5bf1e24d02 fix for below one minite 2015-04-27 09:49:53 +00:00
reality
25347f9006 fix for below one minite 2015-04-27 09:32:22 +00:00
reality
a582600f0f fix for below one minite 2015-04-27 09:30:59 +00:00
reality
ea07d55b9e fix youtube stuff 2015-04-27 09:23:27 +00:00
reality
613b9cd3bd Merge branch 'master' of https://github.com/reality/dbot 2015-04-27 09:21:14 +00:00
reality
81cfa22dcf fix youtube stuff 2015-04-27 09:20:53 +00:00
Luke Slater
2b7077642d Merge pull request #649 from amki/master
Fixed CTCP module and added some new commands
2015-04-26 05:04:03 +03:00
amki
9e7153cf42 Fixed CTCP module and added some new commands 2015-04-26 02:07:38 +02:00
Luke Slater
06f6491d99 Merge pull request #648 from amki/crypto
Moved crypto module to internal node crypto api, remove ciphers, add random
2015-04-25 21:05:17 +03:00
reality
ac2a6036eb meh 2015-04-25 11:05:59 +00:00
reality
744e075697 meh 2015-04-25 11:05:03 +00:00
reality
c0e8290bba meh 2015-04-25 11:03:26 +00:00
reality
be71f31c07 meh 2015-04-25 11:00:51 +00:00
reality
f4d25c0bfa find alias notifies 2015-04-25 10:58:45 +00:00
reality
849067127f find alias notifies 2015-04-25 10:42:30 +00:00
reality
3d92550c76 meh 2015-04-25 10:36:21 +00:00
reality
cb2e4da2ae meh 2015-04-25 10:35:40 +00:00
reality
42952a24e5 meh 2015-04-25 10:34:34 +00:00
reality
9f685779d5 meh 2015-04-25 10:31:44 +00:00
reality
e271ac2885 meh 2015-04-25 10:30:42 +00:00
reality
0108de389b meh 2015-04-25 10:28:47 +00:00
reality
2820dfb0c7 more random recipes 2015-04-25 10:27:22 +00:00
reality
548d4977f2 order 2015-04-25 10:26:35 +00:00
amki
79dd53e4c4 Moved crypto module to internal node crypto api, removed (pretty) senseless cipher command and added random command 2015-04-25 05:48:19 +02:00
reality
15de4c4f5d more random recipes 2015-04-23 15:37:42 +00:00
reality
19442bfe8f typical 2015-04-23 15:18:28 +00:00
reality
8e31ac0ed6 typical 2015-04-23 15:17:38 +00:00
reality
6dd233d51f typical 2015-04-23 15:17:04 +00:00
reality
24c792e4cf oops 2015-04-23 15:13:02 +00:00
reality
9d682455f5 food suggest 2015-04-23 15:11:45 +00:00
reality
e46135d1ec lol 2015-04-23 15:00:56 +00:00
reality
80ebcb76fd hehe 2015-04-23 14:56:47 +00:00
reality
fcb32eaac4 hehe 2015-04-23 14:56:13 +00:00
reality
ff8dc8ce6d oops 2015-04-23 14:54:27 +00:00
reality
4467e9fd5b food 2015-04-23 14:53:33 +00:00
reality
0384a45bf7 hmm 2015-04-21 23:40:45 +00:00
reality
57a2a12814 fix seconds counter (thanks trapdoor) 2015-04-20 20:16:03 +00:00
reality
f6f6de508b change to new youtube api 2015-04-20 20:10:55 +00:00
Luke Slater
25b026cf26 Merge pull request #646 from EddieCurtis/patch-1
Moved period out of ban/kick reason
2015-04-19 15:49:41 +03:00
Eddie Curtis
91e6ef3612 Moved period out of ban/kick reason 2015-04-19 13:47:57 +01:00
Luke Slater
41c56be7da Merge pull request #642 from amki/rss
Updated RSS README to fix #630
2015-04-19 15:44:51 +03:00
Luke Slater
7376c380e7 Update pages.js 2015-04-14 01:50:37 +03:00
Luke Slater
8da13c35a7 Merge pull request #645 from amki/remind
Timers set through remind are now persistent
2015-04-07 00:39:42 +03:00
amki
fc06811907 Fixed bugs, removed debug output, timers now persistent 2015-04-06 23:38:21 +02:00
amki
063fb36567 still doesn't work 2015-04-06 21:25:33 +02:00
amki
7a138804a8 New iteration 2015-04-06 20:59:40 +02:00
amki
b54e5aa22d Started work on persistent timers 2015-04-06 20:46:21 +02:00
Luke Slater
0fdbc5fe68 Update kick.js 2015-04-06 00:51:06 +03:00
Luke Slater
37d5fca1af Merge pull request #644 from amki/remind
Remind now supports messages with spaces and calls the user reminding you
2015-04-05 20:50:07 +03:00
amki
7ac7817101 Remind now supports messages with spaces and calls the user reminding you 2015-04-05 19:48:47 +02:00
Luke Slater
448309dc37 Merge pull request #643 from amki/remind
Added remind module according to #171
2015-04-05 20:38:56 +03:00
amki
64bffd534e Added remind module with ~remind and ~remindme commands 2015-04-05 19:36:56 +02:00
Luke Slater
6b7ff075e4 Update rss.js
lol
2015-04-05 19:36:56 +02:00
amki
4cc8e26232 Updated RSS README to fix #630 2015-04-05 07:00:32 +02:00
Luke Slater
baaa444f42 Update rss.js
lol
2015-04-04 02:29:48 +03:00
Luke Slater
0da96ea9ff Merge pull request #641 from amki/rss
RSS module: URL shortener is now kinda optional + 2 bonus crashfixes
2015-04-04 02:27:55 +03:00
amki
db0c61b369 URL shortener is now optional, errors are being pasted to console 2015-04-04 01:24:50 +02:00
amki
1756ae84ef Fixed 2 crashes when rss database was empty 2015-04-04 00:28:36 +02:00
reality
65d752484f m is not n 2015-04-02 18:46:42 +00:00
reality
300a6c51a1 m is not n 2015-04-02 18:45:32 +00:00
reality
58ef784a1e m is not n 2015-04-02 18:44:37 +00:00
reality
c873d4888d blah 2015-04-02 18:41:38 +00:00
reality
8bdb11e9e1 remember your imports kids 2015-04-02 18:37:52 +00:00
reality
0536ce1efa tz 2015-04-02 18:35:40 +00:00
Luke Slater
6838e269b2 Update april.js 2015-04-01 00:43:06 +03:00
Luke Slater
db661c1229 Update april.js 2015-04-01 00:42:46 +03:00
reality
a07daddccc push 2015-03-31 18:51:53 +00:00
reality
e393fd6fdb ye 2015-03-31 18:50:44 +00:00
reality
3347b67cea optinal single quote 2015-03-31 18:48:57 +00:00
reality
999b6f44ad an support 2015-03-31 18:41:57 +00:00
reality
135a4b421e oops 2015-03-31 18:36:08 +00:00
reality
b7b57da78a shorter timeout and parse out a 2015-03-31 18:35:19 +00:00
reality
417cc7b5f8 set a small timeout 2015-03-31 18:32:18 +00:00
reality
33923aee8b OMG 2015-03-31 18:29:45 +00:00
reality
febddfcac7 update nban usage 2015-03-30 19:02:06 +00:00
reality
a27f789a37 get a random post from a given subreddit 2015-03-28 12:55:06 +00:00
reality
e57b0107f4 bleh 2015-03-24 19:57:49 +00:00
reality
dc2b61b21d bleh 2015-03-24 19:39:09 +00:00
reality
148a7a6693 interpol quote 2015-03-24 19:36:36 +00:00
reality
0a9a5a95d0 more likely 2015-03-24 19:34:12 +00:00
reality
bcdf86d7ff i am not wise 2015-03-24 19:33:06 +00:00
reality
16e9b2d9bd i am not wise 2015-03-24 19:32:19 +00:00
reality
902cbdec3c idk 2015-03-24 19:30:46 +00:00
reality
ac2f7bbccd fix regex examples 2015-03-24 19:26:41 +00:00
reality
33c50671e6 fix regex examples 2015-03-24 19:23:02 +00:00
reality
4d50f1eff2 random should response whatsit 2015-03-24 19:17:54 +00:00
reality
e892b0518a oops 2015-03-23 16:19:57 +00:00
reality
04cf918f7a oops 2015-03-23 16:17:32 +00:00
reality
17840f5c9c karma colour 2015-03-23 16:14:41 +00:00
reality
a2ea8cd260 extract err 2015-03-15 18:52:33 +00:00
reality
323be545ab extract err 2015-03-15 18:51:54 +00:00
reality
b41d01b4ad extract err 2015-03-15 18:49:32 +00:00
reality
22c9a5e011 extract err 2015-03-15 18:46:58 +00:00
reality
b54774994b in days 2015-03-14 14:00:56 +00:00
reality
028f56c289 in days 2015-03-14 13:59:45 +00:00
reality
bde2e5f231 colour and diff 2015-03-14 13:58:15 +00:00
reality
0dac6bd576 b& for 45 years 2015-03-14 13:50:31 +00:00
reality
ce149998d8 more trix 2015-03-14 13:49:30 +00:00
reality
8070875937 trix 2015-03-14 13:47:31 +00:00
reality
65d1c24adf ban thing 2015-03-14 13:45:15 +00:00
reality
148e4a43db oops 2015-03-14 10:17:19 +00:00
reality
46d5df86c2 yes 2015-03-14 10:16:17 +00:00
reality
36372a511c also glob name 2015-03-14 09:59:16 +00:00
reality
e523e35c73 today i have a serious case of the stupids. fix host var 2015-03-14 09:56:55 +00:00
reality
f3b1d0c4ef i actually am an idiot 2015-03-14 09:55:39 +00:00
reality
b8e3f13816 i actually am an idiot 2015-03-14 09:54:41 +00:00
reality
4aa2c05989 concerning 2015-03-14 09:52:51 +00:00
reality
96dc972637 concerning 2015-03-14 09:51:22 +00:00
reality
6fc93344a8 concerning 2015-03-14 09:49:15 +00:00
reality
89384492d1 concerning 2015-03-14 09:47:59 +00:00
reality
ad2448f2a0 concerning 2015-03-14 09:45:13 +00:00
reality
fb61ce21a5 concerning 2015-03-14 09:43:34 +00:00
reality
c779721d52 concerning 2015-03-14 09:42:13 +00:00
reality
840ed71188 store host in notify 2015-03-14 09:24:51 +00:00
Luke Slater
d83a2cab74 Merge pull request #638 from shymega/urlupd1
Updated d3.js again
2015-03-11 11:15:26 +03:00
reality
6c671b1ba7 oops 2015-03-09 13:35:38 +00:00
shymega
1d55c1ebce Updated d3.js again 2015-02-28 16:54:43 +00:00
reality
2f874686b6 fix security bug in imgur module 2015-02-27 09:49:46 +00:00
reality
3d8700a6d2 fix security bug in imgur module 2015-02-27 09:48:21 +00:00
reality
baeeee64d9 no karma from bot (quote abuse) 2015-02-19 17:14:27 +00:00
reality
cdc8cb0d74 limit length of karma thing 2015-02-19 17:12:25 +00:00
reality
cafe173911 Merge branch 'master' of github.com:reality/dbot 2015-02-18 16:12:54 +00:00
reality
d84b94f050 fixnomissingchan 2015-02-18 16:12:48 +00:00
Luke Slater
dda7beea10 Merge pull request #637 from Kagammor/patch-1
Don't show comma if no city is given
2015-02-17 12:13:06 +03:00
reality
77e67b637b oops 2015-02-17 08:49:16 +00:00
reality
c2573f9043 oops 2015-02-17 08:39:57 +00:00
Kagammor
c7733ee382 Don't show comma if no city is given
The OpenWeatherMap API may return weather for areas unlinked to a city, on which body.name will be undefined. This would previously show up as (for example) "[ , United Kingdom]". This simple ternary will only return a comma if it is also returning a city name.
2015-02-17 01:23:51 +01:00
reality
5aeeb77065 geoip 2015-02-15 18:26:25 +00:00
reality
e5ac647de4 oops 2015-02-13 00:17:38 +00:00
reality
2d1cfdd567 no more : 2015-02-11 22:24:53 +00:00
reality
81520a3aab fix indentation 2015-02-09 16:56:29 +00:00
reality
10c300ff2b only one connection to the database across all modules. master db driver in dbType of main config.json 2015-02-09 16:54:59 +00:00
reality
76a59dee55 #note #quiet warns 2015-02-08 21:10:23 +00:00
reality
6b7b5494f6 return fbman to ri results 2015-02-07 21:54:16 +00:00
reality
2f9133fcee return fbman to ri results 2015-02-07 21:53:27 +00:00
reality
e9e1e61540 ext quotecat 2015-02-06 12:40:15 +00:00
reality
fc81fc38a1 trim space from end of karma 2015-02-05 19:49:38 +00:00
reality
7749b2eb65 nope 2015-02-04 21:30:52 +00:00
reality
e8a18fa72f nope 2015-02-04 21:29:32 +00:00
reality
e831a7cfa5 /i 2015-02-04 18:52:35 +00:00
reality
11c303bcaa karma 2015-02-04 17:32:31 +00:00
reality
e426a306ab karma 2015-02-04 17:13:41 +00:00
reality
7ad9a5c6a0 karma 2015-02-04 17:07:18 +00:00
reality
931d2de4f1 karma 2015-02-04 17:06:00 +00:00
reality
4446825458 karma 2015-02-04 17:05:20 +00:00
reality
5cbb0362c0 karma 2015-02-04 17:04:50 +00:00
reality
6adc93f043 lc 2015-02-04 17:02:39 +00:00
reality
4a198e2f64 more karma 2015-02-04 17:00:47 +00:00
reality
164ec47337 fix thing +_+++++ 2015-02-04 16:38:56 +00:00
reality
d97e4969f9 karma 2015-02-04 16:34:59 +00:00
reality
720740de58 -b on thing 2015-01-30 00:07:45 +00:00
reality
b5bb0af0da idk 2015-01-29 23:59:55 +00:00
reality
1cbb57e519 inbuilt -b 2015-01-29 22:24:45 +00:00
reality
29bdb0e91e quietbans 2015-01-29 22:06:17 +00:00
reality
bf920874b1 derp 2015-01-29 21:47:18 +00:00
Luke Slater
eab1004215 Merge branch 'master' of https://github.com/reality/dbot 2015-01-29 21:42:18 +00:00
Luke Slater
57b6b1b7ee fixes 2015-01-29 21:42:09 +00:00
reality
c290b64285 full redir 2015-01-29 21:41:01 +00:00
reality
79a607ba1b weather country 2015-01-28 07:22:32 +00:00
reality
c87c4312ad weather better 2015-01-28 06:26:14 +00:00
reality
f440ffd405 Merge branch 'master' of github.com:reality/dbot 2015-01-28 06:16:25 +00:00
reality
1d10ed86e6 weather 2015-01-28 06:16:17 +00:00
Luke Slater
357fe04058 Merge pull request #635 from shymega/newinstall
Install script fix -URL's and config.json edit
2015-01-26 22:34:24 +00:00
shymega
501c8e66d9 Updated download URL's, and now edits config.json with $EDITOR variable,
or vim if the variable doesn't exist.
2015-01-24 18:19:40 +00:00
reality
ff342bc932 [Close #634] 2015-01-24 17:34:30 +00:00
reality
a101cfe437 domain err catch 2015-01-19 22:59:26 +00:00
reality
b3d7abbc3b debug 2015-01-19 22:33:28 +00:00
reality
4e4da78e0b debug 2015-01-19 22:31:18 +00:00
reality
c412ad0b23 revert 2015-01-19 22:30:04 +00:00
reality
52a5023ef7 asynx != async 2015-01-19 22:28:53 +00:00
reality
552b87c29e async output next 1s delay 2015-01-19 22:28:18 +00:00
reality
e5b8034e0f order by int not string 2015-01-19 22:25:03 +00:00
reality
3f6153a7cf order by int not string 2015-01-19 22:19:34 +00:00
reality
14f3a09c2c date formatting 2015-01-19 22:16:22 +00:00
reality
84e7b5f06e date formatting 2015-01-19 22:12:05 +00:00
reality
0e47ce22ce sort is one of the few functions afforded to the array object naturally 2015-01-19 22:08:54 +00:00
reality
4709a11fad time 2015-01-19 22:06:33 +00:00
reality
5b067094de reports 2015-01-19 21:57:27 +00:00
reality
439fcf567c ye 2015-01-15 02:46:02 +00:00
reality
97f44141b3 Revert "access"
This reverts commit 333c8de2ad973833163211c1617b9f1505ec61a5.
2015-01-15 02:45:07 +00:00
reality
333c8de2ad access 2015-01-15 02:44:00 +00:00
reality
b1697464d9 sustatus 2015-01-15 02:41:11 +00:00
reality
4ca95aa1aa wordcrimes initial 2015-01-12 04:30:31 +00:00
reality
d3633fc21d new db without resolvchan 2015-01-09 21:25:33 +00:00
reality
5621bad05c currency 2015-01-09 01:43:20 +00:00
reality
d732440e3e yeah yeah 2015-01-09 01:11:47 +00:00
reality
b2188ea036 r2rio 2015-01-09 00:53:14 +00:00
reality
0a6f1bd82a gmaps 2015-01-08 18:06:20 +00:00
reality
d0db3b6a53 yes yes 2015-01-07 21:47:12 +00:00
reality
0d86dc4119 yes yes 2015-01-07 21:45:54 +00:00
reality
7e968d38bb period 2015-01-02 21:40:29 +00:00
reality
2c4aad8a23 whoops 2015-01-02 21:39:45 +00:00
reality
54f4d4979c types 2015-01-02 21:38:37 +00:00
reality
e2190444a8 ye 2014-12-24 00:19:25 +00:00
reality
2b31ce12d9 yeh 2014-12-16 02:50:03 +00:00
reality
36b41156a5 Merge branch 'master' of github.com:reality/dbot 2014-12-03 04:16:45 +00:00
reality
0f73bca593 yeh 2014-12-03 04:14:14 +00:00
Luke Slater
d647b35405 Update words.js 2014-11-30 04:01:14 +00:00
Luke Slater
047ed35f83 Update words.js 2014-11-30 03:59:19 +00:00
Luke Slater
72afc1ca0a Update words.js 2014-11-30 03:58:22 +00:00
Luke Slater
ba0d99b60d Update words.js 2014-11-30 03:57:41 +00:00
Luke Slater
f8cfc04ab2 Update words.js 2014-11-30 03:56:25 +00:00
reality
2d8a1da470 like 2014-11-29 05:10:34 +00:00
reality
0cf845f099 like 2014-11-29 05:08:26 +00:00
reality
f0398fe8fc like 2014-11-29 05:03:25 +00:00
reality
42b8b1f6ba like 2014-11-29 05:02:11 +00:00
reality
1a144c6459 etymology 2014-11-28 14:43:16 +00:00
reality
f7fbbc7bd0 and the strings... 2014-11-09 14:05:32 +00:00
reality
1b2f01af94 tell user about warn 2014-11-09 14:04:04 +00:00
Luke Slater
27c150f877 some ufixes 2014-11-09 13:59:00 +00:00
reality
bdbd5ee8e4 Words updates 2014-10-31 17:02:17 +00:00
reality
1b67b04630 like 2014-10-31 04:27:08 +00:00
reality
0c8d0c8143 like 2014-10-31 04:21:33 +00:00
reality
a45c578037 like 2014-10-31 04:19:05 +00:00
reality
d91c014b53 fix web import and bootstrap dl #629 2014-10-27 17:07:04 +00:00
Luke Slater
81b352c306 Merge pull request #627 from reality/betterusers
merge new users into master
2014-10-27 16:41:40 +00:00
Luke Slater
f309348e25 Update run.js 2014-10-22 03:10:24 +01:00
reality
977de65914 web changes for posting 2014-10-21 21:25:50 +00:00
Luke Slater
d7939a59cc changes 2014-10-21 15:08:55 +00:00
Luke Slater
cd92f0c4de updates 2014-10-21 15:08:26 +00:00
Luke Slater
c4828f7ef4 Update web.js 2014-10-19 23:55:45 +01:00
reality
9705f308fd fix wordusers 2014-10-16 16:08:58 +00:00
reality
a68108df07 remember to commit new files 2014-10-03 21:00:57 +00:00
reality
8a5089c0f6 t push:wq
:Merge branch 'betterusers' of github.com:reality/dbot into betterusers
2014-10-03 20:56:15 +00:00
reality
881f828f34 no strict match on chan 2014-10-03 20:56:11 +00:00
Luke Slater
5289efc72c blah 2014-10-03 20:54:30 +00:00
Luke Slater
9ed4c582e2 ffs 2014-10-03 20:45:51 +00:00
reality
a7ccb5ff14 akill 2014-10-03 20:42:41 +00:00
Luke Slater
80cd9ab9d6 Merge branch 'betterusers' of https://github.com/reality/depressionbot into betterusers 2014-10-01 00:29:03 +00:00
reality
d0aab89435 L:Merge branch 'betterusers' of github.com:reality/dbot into betterusers 2014-10-01 00:28:40 +00:00
reality
6d8224bdf1 leafly 2014-10-01 00:28:32 +00:00
Luke Slater
fb3ddf2da8 Update commands.js 2014-09-28 18:48:36 +01:00
Luke Slater
80d9af6279 Merge pull request #624 from amki/rss
Don't crash when rss feed item does not contain pubdate
2014-09-19 14:45:18 +01:00
amki
0a914c820a Don't crash when rss feed item does not contain pubdate 2014-09-18 21:07:29 +00:00
Luke Slater
038af50eaa Merge branch 'betterusers' of https://github.com/reality/depressionbot into betterusers 2014-09-18 03:33:45 +00:00
reality
9733fa6185 pls 2014-09-18 03:33:40 +00:00
Luke Slater
6895ad66f6 Merge branch 'betterusers' of https://github.com/reality/depressionbot into betterusers 2014-09-18 03:32:03 +00:00
reality
6b52141245 try again 2014-09-18 03:31:59 +00:00
Luke Slater
0eb29caf44 Merge branch 'betterusers' of https://github.com/reality/depressionbot into betterusers 2014-09-18 03:29:27 +00:00
reality
e1732ff26a blah 2014-09-18 03:29:20 +00:00
Luke Slater
f8bc0be366 whoops 2014-09-15 21:20:59 +00:00
Luke Slater
d184a251e4 whoops 2014-09-15 21:19:41 +00:00
reality
84ddfb90a6 repair nunsub 2014-09-15 21:12:30 +00:00
reality
83e5a35677 expand flags from hosts 2014-09-14 19:31:22 +00:00
reality
5560f96744 get users with given vhost 2014-09-14 19:02:45 +00:00
reality
2660995aee usage for crypto 2014-09-13 19:52:01 +00:00
reality
e3a6f53537 regex for usage 2014-09-13 19:48:28 +00:00
reality
2570eb99a6 remove tilde prefix for command usage 2014-09-13 19:40:59 +00:00
reality
0ebdb2dbde put udp bind in onload so it has this 2014-09-13 19:23:00 +00:00
reality
b660d9ce21 ok 2014-09-12 14:56:34 +00:00
reality
ac603c3b9c alignment is important mmkay? 2014-09-12 14:53:41 +00:00
reality
9a7827448d fix flashy 2014-09-12 14:52:45 +00:00
Luke Slater
a2a025ad55 Update install 2014-09-11 20:21:16 +01:00
reality
77d9997009 fix nickstealing 2014-09-09 09:52:45 +00:00
reality
402c8e80f4 missing err in readUser on reload ignore repopulation 2014-09-08 21:08:28 +00:00
reality
5551e8545f Merge branch 'betterusers' of github.com:reality/dbot into betterusers 2014-09-08 21:02:16 +00:00
reality
a496526049 fix ignore behaviour with command/module clash 2014-09-08 21:02:10 +00:00
Luke Slater
03bab4e7db some fixes 2014-09-08 10:42:59 +00:00
reality
63ded5b197 that should do it 2014-09-08 10:41:09 +00:00
reality
57742d13f2 fix flag regex 2014-09-06 18:43:26 +00:00
reality
1d9765c95b correct user ids 2014-09-06 12:01:32 +00:00
reality
64e7294233 final fixes 2014-09-05 13:51:51 +00:00
reality
15e3971f11 Merge branch 'betterusers' of github.com:reality/dbot into betterusers 2014-09-05 12:06:16 +00:00
reality
64cdd374bc fix profiles. also the fact it was getting all the users onLoad is probably a badthing 2014-09-05 12:06:10 +00:00
Luke Slater
8d9ef6365e Update atheme.js 2014-09-05 12:38:33 +01:00
reality
bea3283b05 no offline messages support for those using anything but my changes to atheme. gg -.- 2014-09-05 11:29:25 +00:00
reality
8c5e871640 report report (it works) 2014-09-05 10:42:30 +00:00
reality
7cb53a8b5a now it works 2014-09-05 09:15:05 +00:00
reality
24d14e7005 read flags 2014-09-05 08:51:48 +00:00
reality
e83b4af33f move charybdis module to atheme 2014-09-04 15:26:28 +00:00
reality
8dfe1a37c4 remove getchannel stuff 2014-09-04 15:25:21 +00:00
reality
ef250fbc05 fix resolveuser references 2014-09-04 14:54:49 +00:00
reality
e096daa605 fix getUser calls 2014-09-04 14:48:20 +00:00
reality
c519727b6c fix login 2014-09-04 14:41:57 +00:00
reality
78057dca3c update web to use new express version 2014-09-04 14:19:23 +00:00
reality
b18a61ebd1 fix reports and warning 2014-09-04 13:43:53 +00:00
reality
34acae025b fix most of the sstats stuff, still got to do merge trigger 2014-09-04 13:04:15 +00:00
reality
1037070bff fixes for merge and setaliasparent, basic sstats functionality 2014-09-04 12:15:11 +00:00
reality
8ba4db33a7 some bug fixes 2014-09-04 10:15:52 +00:00
reality
905ced9485 add merge users command and fix up strings 2014-09-04 09:51:39 +00:00
reality
0a4240f3db replace users with new modules 2014-09-04 09:36:57 +00:00
reality
be07c36294 tings 2014-09-04 09:30:22 +00:00
reality
b950426d7b well, there's a start 2014-09-04 08:27:46 +00:00
Luke Slater
1a590bd678 Merge pull request #623 from shymega/master
dbot - install script fix
2014-09-03 07:28:20 +01:00
Dominic Z. Rodriguez
b1a6a85ff7 Just a minor fix to a filename 2014-09-02 18:58:32 +01:00
Dominic Z. Rodriguez
87bc11061d Updated the shell script 'install' for dbot, download urls for bootstrap and d3js were not working. 2014-09-02 18:53:36 +01:00
Luke Slater
c691ce38ed whoopsie doodle 2014-08-19 00:49:00 +01:00
reality
ad08b24c3e stagger joins 2014-08-18 23:13:55 +00:00
Luke Slater
964467464c [Close #619] 2014-07-27 14:05:21 +01:00
reality
311f8034f4 devoice on quiet 2014-07-23 16:08:05 +00:00
Luke Slater
dd8e1fccd7 Update config.json.sample 2014-07-22 22:20:14 +01:00
reality
30ffd22599 ~squestion 2014-07-22 11:33:36 +00:00
reality
48ba900ea1 new post with less info 2014-07-22 11:28:54 +00:00
reality
45f1b3c311 whoops 2014-07-21 21:34:04 +00:00
reality
70040a0ed3 curr chan ban 2014-07-21 21:31:04 +00:00
reality
7b3489225c radio thing 2014-07-21 13:30:18 +00:00
reality
ba393020b2 include - in #hashtag 2014-07-21 08:56:57 +00:00
reality
776bd6d7d6 dont post radio if undefined 2014-07-19 19:58:22 +00:00
reality
aab0e8b6db better request 2014-07-19 16:57:45 +00:00
reality
80ff91b609 Merge branch 'master' of https://github.com/reality/dbot 2014-07-14 22:54:42 +00:00
reality
ad35f9cc82 change notify event trigger 2014-07-14 22:54:23 +00:00
reality
c0e8a588ec change youtube to yt 2014-07-14 13:42:56 +00:00
reality
60f9c5ef29 change youtube to yt 2014-07-14 13:41:29 +00:00
reality
18f7f64b47 unescape reddit titles for all links 2014-07-12 18:19:59 +00:00
reality
427bb7c4b8 unescape reddit titles 2014-07-12 18:15:56 +00:00
reality
1aec6dcd34 update jsbot 2014-07-11 18:13:59 +00:00
reality
7ca178fced fix merge? 2014-07-08 11:33:56 +00:00
reality
01b2d22059 test 2014-07-07 11:06:38 +00:00
reality
f621fbc38e update jsbot 2014-07-07 10:43:03 +00:00
reality
9fe8b3ab43 #warn 2014-06-29 12:09:47 +00:00
reality
4aed770b7e autoquietwarn 2014-06-26 22:19:18 +00:00
reality
9530bead9c fix web access 2014-06-26 22:03:45 +00:00
reality
5ecd3054b3 move warn to api and rmwarning 2014-06-26 21:50:33 +00:00
reality
1af4788de0 you fool you foolish fool 2014-06-26 19:50:45 +00:00
reality
0697f0b5a0 ~question 2014-06-26 19:40:54 +00:00
reality
610a8cfabf also add a link for removals 2014-06-19 15:44:31 +00:00
reality
3250e25aa0 add link output to qadd 2014-06-19 15:22:25 +00:00
reality
ad0133b948 rss.title not feed.title 2014-06-19 15:11:04 +00:00
reality
3a2374ad59 dont repeat items with the same title within a bound of 30 2014-06-19 14:51:54 +00:00
reality
09e91bf817 Merge branch 'master' of github.com:reality/dbot 2014-06-19 14:42:03 +00:00
reality
daa5c9ccc2 some updates to the rss module 2014-06-19 14:41:57 +00:00
Luke Slater
abab37b71e Merge pull request #618 from RCTrapdoor/patch-3
Update regex.js
2014-06-19 14:33:46 +01:00
RCTrapdoor
71bda91639 Update regex.js
Enable users to correct other users suffixing usernames with either comma or colon.
2014-06-19 14:21:54 +02:00
reality
c50975672e fix 2014-06-16 16:20:26 +00:00
reality
fbdec17670 dont post the thingy if there is no category or author 2014-06-16 15:53:27 +00:00
reality
ecec80ac58 add puush module 2014-06-09 21:03:25 +00:00
reality
f1442edf34 fix web perms 2014-06-06 01:16:30 +00:00
reality
51426264d6 first step of [#616] 2014-06-03 22:47:52 +00:00
Luke Slater
58b9e430ad Merge pull request #615 from amki/rss
Added rss feed module
2014-06-02 17:55:15 +01:00
reality
628b7bc378 140 chars in synopsis 2014-06-02 02:13:04 +00:00
reality
6990a10d9c time thing 2014-05-25 21:16:28 +00:00
reality
131233e7d0 ncount 2014-05-25 20:47:30 +00:00
reality
80e9f245ab what 2014-05-25 19:12:58 +00:00
reality
4f8ce61909 order thethings 2014-05-25 19:03:28 +00:00
reality
569265f1c7 lowercase 2014-05-25 18:24:13 +00:00
reality
4acf17f636 tags 2014-05-25 17:54:46 +00:00
reality
2864c0fa7f whoops 2014-05-25 17:22:08 +00:00
reality
6218def4df tags or whatever 2014-05-25 17:16:53 +00:00
amki
b5a8929931 Fixed outputting multiple posts per check 2014-05-24 22:22:34 +00:00
amki
639467fe27 Fixed crash in addrssfeed 2014-05-24 18:15:12 +00:00
amki
73ce7c6bfd Add feedparser to npm dependencies (rss module) 2014-05-24 17:28:35 +00:00
amki
bc00fabb81 Roi requested the RSS module use goo.gl shortened links 2014-05-24 17:16:46 +00:00
amki
64f5f61a0a Only use one timer to update all feeds. Properly save lastPosted date 2014-05-24 15:26:28 +00:00
amki
61471e80dc Fixed feeds having seperate last posted times 2014-05-24 00:46:01 +00:00
amki
fc4ba61e86 Only post when there is something new, smaller fixes 2014-05-23 23:38:41 +00:00
amki
358e8b95bb Automatic feed reloading and timed requests work 2014-05-23 23:38:41 +00:00
amki
f38af0836c Added RSS module, able to housekeep feeds for now 2014-05-23 23:38:40 +00:00
reality
6b2f2f8484 rt instead of mymovieapi 2014-05-22 16:25:52 +00:00
reality
14bb252a73 Announce module 2014-04-27 21:15:04 +00:00
reality
ef1e514c54 fix report trim 2014-04-18 18:18:23 +00:00
reality
f48e4c3942 something something channel users 2014-04-11 23:19:31 +00:00
reality
5644675b74 double whoops 2014-02-27 01:40:50 +00:00
reality
c97d947087 whoops 2014-02-27 01:37:47 +00:00
reality
0069bdf5a4 goodreads ~books 2014-02-27 01:34:40 +00:00
reality
f2527a6363 fix #614 2014-02-26 23:24:56 +00:00
reality
93022fa4f2 concurrise the imgur pulls 2014-02-26 15:49:44 +00:00
reality
8c93a75e04 add goodreads 2014-02-26 15:10:11 +00:00
reality
4f3b648bdd add prefix 2014-02-20 20:45:10 +00:00
reality
8d407c39b8 use input not params 2014-02-20 20:42:59 +00:00
reality
eb84abb470 change ~calculate to ~wr 2014-02-20 20:42:09 +00:00
reality
c8d46d73a3 fix tvdb link 2014-02-20 20:33:20 +00:00
reality
ee58d0fdb3 t push:Merge branch 'master' of github.com:reality/dbot 2014-02-20 20:27:27 +00:00
reality
b9894b5597 add nerfed fix 2014-02-20 20:27:21 +00:00
Luke Slater
b72562b0bf Update README.md 2014-02-20 20:20:26 +00:00
reality
721ed55598 fix up wolframalpha 2014-02-20 20:19:44 +00:00
reality
03f2ac16b5 everything except wolfram working 2014-02-20 20:10:45 +00:00
thoso
3ea9fb8c68 500px crappy photo fix 2014-02-20 20:50:12 +01:00
thoso
408707157a Unit module fix 2014-02-20 20:25:50 +01:00
reality
9ec94c889a fix the radio 2014-02-20 17:38:58 +00:00
thoso
c6fdd3bdbc 500px random popular photo 2014-02-20 08:40:24 +01:00
thoso
fb14f24927 TVDB module
Added a tvdb module, needs to request apikey. may or may not work due
to tvshow array.
2014-02-20 07:23:25 +01:00
thieson
7f8209544e Merge pull request #2 from reality/master
Update udp.js
2014-02-20 06:37:24 +01:00
thoso
f21745305e Only known users can add quotes
May not work due to callback inside dbot.users.api.isKnownUser(…)
2014-02-20 06:32:46 +01:00
thoso
df87621241 sample fix 2014-02-20 06:09:16 +01:00
thoso
b369ce3a0c Various README.md's and cleanups 2014-02-20 06:06:02 +01:00
thoso
d1b72fe443 Added Sample folder for (easier) module development. 2014-02-20 04:33:56 +01:00
thoso
ade1dcd5e8 typo fix 2014-02-20 01:48:04 +01:00
thoso
ed433977c7 config.json s 2014-02-20 00:56:09 +01:00
thoso
8f8636c509 Added Wolfram Alpha module 2014-02-20 00:52:42 +01:00
thoso
b43be1f900 Adding a unit converter
Due to issue #596 I coded a basic unit converter to convert time,
distance, mass, volume and digital values. It depends on node-units.

Also, fixed a typo.
2014-02-19 22:19:36 +01:00
Luke Slater
3beee89f00 Update udp.js 2014-02-18 18:47:43 +00:00
thieson
7537d85084 requesting music for tripradio
Adding a command to ping the DJ that a user requests a song.
2014-02-18 17:17:39 +01:00
thieson
566c91a2b6 Merge pull request #1 from reality/master
pull
2014-02-18 16:09:41 +01:00
reality
2c1acab761 try abort 2014-02-17 20:51:20 +00:00
reality
a38f8df657 whoops 2014-02-17 20:42:24 +00:00
reality
e4997cd915 fuck timers 2014-02-17 20:31:20 +00:00
reality
0913f382d7 missing bing 2014-02-17 20:13:29 +00:00
reality
21eab082bf fuck lag 2014-02-17 20:11:11 +00:00
reality
748b42cff0 radio 2014-02-17 20:00:31 +00:00
reality
2bb307a462 ahem 2014-02-07 20:45:14 +00:00
reality
33c48f854c nickserv freeze account on ~nban 2014-02-07 15:20:24 +00:00
reality
1751c197b6 fix [#602] 2014-02-04 00:58:09 +00:00
reality
27f26da0e5 Merge branch 'master' of github.com:reality/dbot 2014-02-03 17:37:47 +00:00
reality
39d0bd7058 Quiet no longer uses chanserv. Some cleanup of host code. Should fix [#601] 2014-02-03 17:37:38 +00:00
Luke Slater
8302c83001 close #543 2014-02-02 05:19:48 +00:00
Luke Slater
eaf5e97266 PART ONE #543 I THINK YES 2014-02-02 05:18:44 +00:00
reality
68e13e7bcd fix the poll views 2014-01-29 22:42:16 +00:00
reality
faaee59116 yt https 2014-01-27 01:45:00 +00:00
reality
349f283af6 let the debugging begin 2014-01-25 14:35:53 +00:00
reality
4b8363c9d1 maybe fix 2014-01-10 23:49:33 +00:00
reality
8934ebed1d use voice auth on alt nick 2014-01-06 22:36:56 +00:00
reality
62efc4b2b9 fix ignore for multiple nicks and whatever 2014-01-06 18:19:18 +00:00
reality
36aab19204 only do notify host lookup on given channels in the config 2014-01-06 18:05:44 +00:00
reality
502d9c5ae8 update jsbot 2014-01-06 17:42:01 +00:00
reality
b86efbc3c2 return the correct lastly played game 2014-01-05 03:17:42 +00:00
reality
2204c910b9 that will soh wye 2014-01-04 17:59:14 +00:00
reality
a4a6689d38 update jsbot 2014-01-04 17:08:19 +00:00
reality
b9926a154c fix up the nick before action fix. this should be more efficient (plus it is prettier) 2014-01-04 03:51:31 +00:00
reality
023dafc4cb update jsbot 2014-01-04 03:25:50 +00:00
reality
2fac33c2e7 fix module list on index 2014-01-02 13:11:42 +00:00
reality
02d18245c3 fix aliasing 2013-12-31 16:06:19 +00:00
reality
130113db50 ~server 2013-12-31 01:43:07 +00:00
reality
036cdb0740 fix log ignore hook for setwebpass 2013-12-30 14:16:03 +00:00
reality
5941d3f1bd fix help output 2013-12-29 19:11:44 +00:00
reality
a4009d7ff3 fix regex glober 2013-12-29 18:47:31 +00:00
reality
a554b8d1cf fix all the module regexen 2013-12-29 18:38:24 +00:00
reality
1a5f809bdc fix the commands 2013-12-29 18:23:35 +00:00
reality
2677834aad fix regexen 2013-12-29 18:19:17 +00:00
reality
c73deb5974 fix some recursions in admin 2013-12-29 18:15:16 +00:00
reality
6204df19c0 initial support for optional command prefix. module commands can currently either use ~command or just command as key, since module loader implements legacy support by shifting the key. there may be a couple of bugs too if there are any recursive commands 2013-12-29 18:13:59 +00:00
reality
6d28aa272b fix NICK without talking 2013-12-29 11:09:00 +00:00
reality
8e734d895f that should learn it 2013-12-29 10:39:03 +00:00
reality
2ae2b427b0 what if i specifically ask for json 2013-12-27 16:38:59 +00:00
reality
6817c4568b yep 2013-12-27 16:37:37 +00:00
reality
b74ba66a87 test 2013-12-27 16:36:34 +00:00
reality
e0c2ec36f8 syntax is important 2013-12-27 16:35:42 +00:00
reality
b008f28406 wow 2013-12-27 16:35:04 +00:00
reality
5c34719ad1 db 2013-12-27 16:31:52 +00:00
reality
563a9adaf9 etymology 2013-12-27 16:24:16 +00:00
reality
18780b59b0 add crypto-js to the npm dependencies, merge #600 [Close #600] 2013-12-26 17:09:12 +00:00
amki
76b6371498 Fixed .js comment 2013-12-26 06:59:56 +00:00
amki
4b4f0a1608 Fixed crypto readme 2013-12-26 06:55:21 +00:00
amki
7a51fdf524 Added crypto module 2013-12-26 06:55:12 +00:00
reality
75b4b4e2c2 add process to install 2013-12-24 05:03:06 +00:00
reality
5a676220dc revert 2013-12-24 03:22:04 +00:00
reality
0e46741d9a quiet fix 2013-12-24 03:19:54 +00:00
reality
aaa924d9d8 should fix channel ignores 2013-12-24 00:29:00 +00:00
reality
fe0cbf048b remove debugging. note: offload timers to appropriate clllllosure 2013-12-22 04:09:37 +00:00
reality
148535e7de temp disable the thingie 2013-12-21 23:33:19 +00:00
reality
72ac41d632 that should fix the shitty regex too 2013-12-21 23:24:18 +00:00
reality
ca5357ea49 rekt 2013-12-21 23:19:11 +00:00
reality
4dd774f290 de debug in da lebug 2013-12-21 23:15:05 +00:00
reality
c3ffe8d729 this should clean up the timers properly 2013-12-21 22:58:36 +00:00
reality
47d1f3ea31 reddit debug 2013-12-21 19:00:00 +00:00
reality
633e233d9d hes got a knot in his tail 2013-12-20 13:50:32 +00:00
reality
c1f3905672 destroy ints on destroy 2013-12-19 20:28:27 +00:00
reality
63e1344851 missing bind 2013-12-19 20:16:19 +00:00
reality
3cd6c91eda whoops 2013-12-19 20:11:54 +00:00
reality
0422c3702d do the thing thing 2013-12-19 20:02:50 +00:00
reality
44a3b4e7c6 title fir thing thing 2013-12-19 19:06:17 +00:00
reality
c48832a2bc use the whatsit oh shit 1% battery sjiaofjdisaojfodsa 2013-12-19 18:53:35 +00:00
reality
4089fee13c access control on the thingie whatsit 2013-12-19 18:51:49 +00:00
reality
b0d41fb490 remove the debug output thing 2013-12-19 18:50:23 +00:00
reality
f04da64b21 something something reddit feeds 2013-12-19 18:48:49 +00:00
reality
9c17803e03 this should do it 2013-12-13 00:08:20 +00:00
reality
2cb8c4fc10 this is what you get for not modulating properly you shit 2013-12-12 23:49:40 +00:00
reality
5e1dcd4d30 pass module links to each page 2013-12-12 19:19:44 +00:00
reality
eb348848e6 this commit either a) Closes #598 or b) kills us all. Hold onto your coconuts. 2013-11-29 06:16:33 +00:00
reality
e66df67913 filter out duelling network screenshot SINCE YOU SAID PLEASE 2013-11-25 16:33:27 +00:00
reality
05ebfd1dfd handle reddit short link whatsits 2013-11-20 10:25:05 +00:00
reality
61c4afd8aa jaja 2013-11-19 00:16:17 +00:00
reality
1ef1a6cf34 there was another error 2013-11-04 21:55:10 +00:00
reality
068286744f fix warn strings 2013-11-04 21:46:15 +00:00
reality
3d3203b823 change ~game to ~playing 2013-11-04 19:29:51 +00:00
reality
696aef6a6f lets try this then 2013-11-02 21:51:20 +00:00
reality
2ce0e67d4b well lets give this a try 2013-11-02 21:40:10 +00:00
reality
fc415aa6c6 fix lastfm 2013-10-31 23:11:57 +00:00
reality
39f36e146e fix dent 2013-10-30 17:13:36 +00:00
reality
f45084e01a fixt 2013-10-29 22:45:51 +00:00
reality
734f53d9fa strings of project in german 2013-10-29 22:37:38 +00:00
reality
d093fafbe9 whoopsies 2013-10-29 22:16:16 +00:00
reality
0e72143945 the german language - sponsored by roi 2013-10-29 22:07:20 +00:00
reality
0ebae76732 TRANSLATIONS FROM ROI 2013-10-29 21:39:26 +00:00
reality
5541981d4e whats all this then ~scrobbliest 2013-10-29 20:30:50 +00:00
reality
9d7093e6f2 ~lastfm playcount whatsit 2013-10-29 20:16:08 +00:00
reality
ea0aab80e2 tastiest caching 2013-10-29 16:17:22 +00:00
reality
ba8a603e26 dont compare if lfm is == 2013-10-29 16:03:19 +00:00
reality
13a2c465ae null chekc in profile 2013-10-29 15:52:20 +00:00
reality
1920b4fd03 some debug output for tastiest 2013-10-29 15:49:47 +00:00
reality
93c53b93e2 ~tastiest 2013-10-29 15:45:00 +00:00
reality
41fe000bf4 gooood sam 2013-10-28 17:03:08 +00:00
reality
7c1b1066f9 basic charybdis flag reference for chanserv (well its atheme) and chanmodes 2013-10-28 16:44:37 +00:00
reality
055e865628 games command 2013-10-28 16:11:16 +00:00
reality
e8c0d54b02 bleh 2013-10-28 14:55:34 +00:00
reality
c1ac7f035d sight 2013-10-28 14:53:36 +00:00
reality
1d2a5f891e /home/reality/Projects/dbot/modules/steam/steam.js:101 2013-10-28 14:50:21 +00:00
reality
912df73b56 such crashy 2013-10-28 14:49:09 +00:00
reality
7a4dc61412 whoops 2013-10-28 14:39:44 +00:00
reality
dc0785fe2e currently playing and server info 2013-10-28 14:38:35 +00:00
reality
70a2a77cc0 le derp 2013-10-28 13:59:42 +00:00
reality
0fa228a749 some better output 2013-10-28 13:58:58 +00:00
reality
d910b116c6 basic steam module 2013-10-28 13:43:35 +00:00
reality
07206a0ac3 artists 2013-10-25 15:36:53 +00:00
reality
0fac0ac948 ability to set a custom resolver function on commands to gain info, applied this pattern to lastfm 2013-10-25 15:26:53 +00:00
reality
956b947a4c stupid sexy trapdoor 2013-10-24 22:17:10 +00:00
reality
a28ec17a6d pass some limit params 2013-10-24 20:35:29 +00:00
reality
96926ab5fa fancy ass too complicated suggestion thing + lastfm module rewrite w/ proper api 2013-10-24 20:31:49 +00:00
reality
6d81b21b43 ~taste 2013-10-24 18:59:20 +00:00
reality
cf0c6f19c4 hopefully fix mergeusers for the last time 2013-10-24 16:00:15 +00:00
reality
a1826e5c95 that should do it 2013-10-24 12:33:50 +00:00
reality
8e791ed581 look at what others are listening to, fix output if user doesnt have lastfm proeprty set 2013-10-24 12:30:53 +00:00
reality
614520443f get a youtube link for last fm ~listening. note: clean up yt api later 2013-10-24 09:47:56 +00:00
reality
1c1ba2ef02 strings for lastfm 2013-10-24 09:37:54 +00:00
reality
93b751af29 output prefix 2013-10-24 09:33:48 +00:00
reality
fbf1bc1ae2 distinction between now playing and last playedd 2013-10-23 20:46:32 +00:00
reality
9d48917d09 tings 2013-10-23 20:25:42 +00:00
reality
7f2d813c8c lastfm module 2013-10-23 20:15:23 +00:00
reality
1e995d7bba fix profile 2013-10-23 19:53:14 +00:00
reality
80b76c9325 fucking idiot 2013-10-23 11:46:07 +00:00
reality
b01fce2cc8 [Close #595] 2013-10-23 11:41:22 +00:00
reality
4537651367 lets try that 2013-10-23 10:00:40 +00:00
reality
9369fd8d05 correct the date format 2013-10-22 16:52:30 +00:00
reality
a3f1341daf double whoops 2013-10-22 16:49:30 +00:00
reality
5c0a9d9300 whoops 2013-10-22 16:48:33 +00:00
reality
d044232cd0 date info for sstats 2013-10-22 16:45:52 +00:00
reality
fdfb94371e whoops 2013-10-22 14:45:21 +00:00
reality
de1d8d67d8 no final callback on merged words 2013-10-22 14:43:18 +00:00
reality
1c0b3d5780 apparently undefined is not a function. who knew? 2013-10-22 14:38:10 +00:00
reality
2bd9b081f5 fix missing sstats binds 2013-10-22 14:35:37 +00:00
reality
903427e1ef add word to the actual record 2013-10-22 14:25:53 +00:00
reality
35c59d4c72 report emit 2013-10-22 12:07:38 +00:00
reality
0088d88af6 ensure existence of hosts and tempBans 2013-10-22 08:46:22 +00:00
reality
0649a2c0c9 further closing of #592 2013-10-21 15:40:45 +00:00
reality
632f6e4218 split report up into different files [Close #592] 2013-10-21 15:40:09 +00:00
reality
ead2d21a35 <3 2013-10-20 19:12:07 +00:00
reality
d714b2c0be lowercase all ~word related input 2013-10-20 18:57:15 +00:00
reality
fd400cf3ea small tings 2013-10-20 18:56:39 +00:00
reality
aed155d5a2 ffs 2013-10-20 18:53:27 +00:00
reality
b3a558d81c double derp 2013-10-20 18:53:08 +00:00
reality
f6b8ff9030 derp 2013-10-20 18:51:14 +00:00
reality
f217289e9d strip punctuation 2013-10-20 18:49:19 +00:00
reality
c56c7d2664 lowercase the thing 2013-10-20 18:44:02 +00:00
reality
c372efc3eb wordusers highscore thing 2013-10-20 18:42:00 +00:00
reality
9746641f48 track words and shit yo 2013-10-20 18:29:54 +00:00
reality
e45aa0bcde 24 horu clock to appease roi 2013-10-20 17:55:05 +00:00
reality
a721d82e76 the thing the thing 2013-10-20 17:50:19 +00:00
reality
5a3b936aff fix the regex 2013-10-20 17:48:58 +00:00
reality
2f3c6f9206 ~time command 2013-10-20 17:47:40 +00:00
reality
708e3e0b96 the thing the thing 2013-10-20 16:41:08 +00:00
reality
a2cb958b73 oh it was that easy lol 2013-10-20 16:37:46 +00:00
reality
e40a10dbdc whoops 2013-10-20 16:36:40 +00:00
reality
d568562cad eh that should do it 2013-10-20 16:35:12 +00:00
reality
f492ead7d6 whoops 2013-10-20 16:22:28 +00:00
reality
c611487f42 mite b cool 2013-10-20 16:16:21 +00:00
reality
d0ac927b92 useful error message when attempting to log in with server what dont exist innit 2013-10-20 14:25:43 +00:00
reality
54a0a96cbc ~last thing 2013-10-17 14:31:05 +00:00
reality
44316a5de1 efficiency and command merging 2013-10-17 12:46:55 +00:00
reality
0db0abeb6a shoutiest and wordiest 2013-10-17 11:50:34 +00:00
reality
906291234b ~uncouth 2013-10-17 11:46:50 +00:00
reality
74af9642e1 make it more efficient or whatever 2013-10-17 11:42:05 +00:00
reality
a828536e97 cloudest 2013-10-17 09:16:50 +00:00
reality
10a46a3bde overall ~loudest 2013-10-17 09:10:01 +00:00
reality
bb37adc63d allow curse incrusions 2013-10-17 04:48:45 +00:00
reality
1f3dd159b3 lowercase the whatist 2013-10-17 04:15:12 +00:00
reality
2cd538e1eb words data 2013-10-17 03:59:29 +00:00
reality
ffd60654b1 inception times for all 2013-10-17 03:06:17 +00:00
reality
fc17201f35 derp derp 2013-10-16 15:22:45 +00:00
reality
d7d8c34167 basic sstats module with ~lines and ~clines because i love sundown 2013-10-16 15:12:05 +00:00
reality
96db56a25c exclude common screenshot resolutions for ~ri 2013-10-16 08:15:00 +00:00
reality
785df48d7c prototype for question module 2013-10-15 10:15:49 +00:00
reality
05f2fdb8a3 fix the quote linky thingy on the web whatsit 2013-10-15 06:06:16 +00:00
reality
3df467e35e whoops 2013-10-13 04:51:15 +00:00
reality
439d25f9b0 change ~film to ~imdb 2013-10-13 04:47:58 +00:00
reality
3dfa3be2e1 whops 2013-10-13 04:19:21 +00:00
reality
e9605b60d3 i think this do it 2013-10-13 04:17:17 +00:00
reality
9b036039c5 this may be hilariously broken 2013-10-13 01:25:33 +00:00
reality
110f23ca2f chan_redirs in report [close #591] 2013-10-13 00:29:34 +00:00
reality
56616d6bdf imdb link handler 2013-10-12 22:58:34 +00:00
reality
7c621aeae2 replace rottentomatoes module with new fancier imdb module 2013-10-12 22:31:57 +00:00
reality
2f747d618c basic rotten tomatoes module with a search thing 2013-10-12 21:46:04 +00:00
reality
7046539f29 have both youtube link getters use the same formatLink function 2013-10-08 15:03:38 +00:00
reality
f87f6a37d4 fix ternary and [close [#585]] 2013-10-08 14:51:44 +00:00
RCTrapdoor
e43ead6832 Look at my sexy inline if statement, LOOK AT IT 2013-10-08 16:42:42 +02:00
reality
bf0c277ad6 Change sep. char to comma for YT merge [Close #589] 2013-10-08 13:08:57 +00:00
RCTrapdoor
b6d7a92b32 Padding left zero on seconds <10, (5:09 instead of 5:9) as well as thousands separator on viewCount
I'm not entirely sure if the thousands separator will work like that, but there's only one way to find out.
2013-10-08 10:49:33 +02:00
reality
f8e4c52616 new jsbot 2013-09-24 21:20:03 +00:00
reality
6e1238206d change default warn access to power user 2013-09-24 11:52:23 +00:00
reality
9e98f2799d remove the bs formatting shit from run innit 2013-09-24 01:35:25 +00:00
reality
93915c7c5f derp 2013-09-16 02:07:37 +00:00
reality
bf996f2fd1 that should do it 2013-09-13 14:54:17 +00:00
reality
ef4ceac61e fix crash when imgur shit innit 2013-09-13 14:35:19 +00:00
reality
3ff165f323 that should do it.. maybe.. 2013-09-10 18:25:20 +00:00
reality
a3f9e238bf logging fix + caching crash fix 2013-09-10 18:11:39 +00:00
reality
fbc0aa59c2 this should be somewhat faster at filling the cache 2013-09-10 17:21:05 +00:00
reality
d271b6672f ri cache, replace ri with ssri, move ri to lri 2013-09-10 17:07:34 +00:00
reality
df7d4149c6 ~ssri 2013-09-10 16:29:23 +00:00
reality
46de1a5fac present for roi 2013-09-09 19:30:23 +00:00
reality
64fdca5097 add time to ythe youtube module 2013-09-09 18:37:15 +00:00
Luke Slater
4f36d2608f Update strings.json
add time to yt thing
2013-09-09 19:35:05 +01:00
reality
6ded78bb5e LAME 2013-09-09 18:33:46 +00:00
reality
e4b46452e5 make the index links a bit nicer 2013-09-08 16:25:20 +00:00
reality
3089d2bd1b that will do for now [#585] 2013-09-08 11:20:48 +00:00
reality
c97347a228 that will do for now [#585] 2013-09-08 11:20:37 +00:00
reality
1f0c11e8c3 derp#2 2013-09-08 10:54:30 +00:00
reality
8db41809fd whoops 2013-09-08 10:52:53 +00:00
reality
e80b695dfa crash error reporting [#468] 2013-09-08 10:51:21 +00:00
reality
c46f5c4f9b fix nunban 2013-09-07 23:02:04 +00:00
reality
7ec7537b7d include user in missing notifies 2013-09-07 19:28:46 +00:00
reality
17bd41d3ef fix the chain 2013-09-07 18:12:02 +00:00
reality
6b9c7d6cf0 that should be channel.nicks 2013-09-07 18:03:59 +00:00
reality
a238994e0f voiced in chan can quiet 2013-09-07 17:55:48 +00:00
reality
4940eec5ce i think this fix it 2013-09-02 21:32:46 +00:00
reality
b1c41008ce ~~-nick-~~ 2013-08-31 22:57:29 +00:00
reality
306b28bf93 more translations from gian-maria.daffre@giammi.com 2013-08-31 19:58:17 +00:00
reality
b4531e2c8f usage for quiet 2013-08-31 16:56:24 +00:00
reality
9848785d38 do that thing wot i said in [#581] 2013-08-31 16:25:11 +00:00
reality
24ccdeac8f store channel in missing notifies 2013-08-31 15:47:56 +00:00
reality
f9ca9a76d9 fix [#580] 2013-08-31 15:38:57 +00:00
reality
503326be04 fix missing link 2013-08-31 15:23:27 +00:00
reality
0cd9e6e343 sidething 2013-08-31 15:20:38 +00:00
reality
3b304bf769 add the pm bit 2013-08-31 13:33:10 +00:00
reality
dbccd67b20 why do colons and semicolons look so similar 2013-08-31 13:31:45 +00:00
reality
d7640f1c20 include channel in logs 2013-08-31 13:30:24 +00:00
reality
1675700073 default timezone 2013-08-31 12:57:34 +00:00
reality
6b128ec798 finish [#578] 2013-08-31 12:53:45 +00:00
reality
8e4ac8d503 do that thing wot i said for [#578] 2013-08-31 12:38:25 +00:00
reality
16b9e0e415 link to the things right [#577] 2013-08-31 12:23:50 +00:00
reality
9e67c94074 do that thing what i said for [#577] 2013-08-31 12:17:06 +00:00
reality
c09e9de9f9 remove the old install file 2013-08-31 12:00:29 +00:00
Luke Slater
a90083b287 Merge pull request #576 from iceTwy/master
Update installation files, add default redis port for listening
2013-08-30 22:05:48 -07:00
iceTwy
0ea80369cf install must be run with bash, not sh 2013-08-31 03:15:20 +02:00
iceTwy
26821a3ac5 install must be run with bash, not sh 2013-08-31 03:14:18 +02:00
iceTwy
7bc6fc988f Update node.js module dependencies 2013-08-31 03:11:30 +02:00
Luke Slater
017822d422 Update install.sh 2013-08-30 12:27:33 +00:00
reality
de3eb90ab5 ok i fixed it 2013-08-30 02:55:20 +00:00
reality
3ce44418e7 fix eat cheese for twistington 2013-08-30 02:47:44 +00:00
reality
8b8400f437 notfy fixy 2013-08-29 21:35:05 +00:00
reality
20e76c3076 fix for the overflow 2013-08-29 21:32:48 +00:00
reality
6d1d5d0afe done [#575] 2013-08-29 21:12:45 +00:00
reality
26bce2e8a0 fix for currentnick 2013-08-29 20:07:30 +00:00
reality
2f2c702c8f fix ~setaliasparents, implement mobile aliases [#573] 2013-08-28 20:22:56 +00:00
reality
c5a3d75d29 fix warn 2013-08-28 17:35:11 +00:00
reality
4b36fc33b1 fix the ban host thing 2013-08-28 12:25:33 +00:00
reality
8aa9842091 lc 2013-08-27 23:32:31 +00:00
reality
d718b81d79 bleh 2013-08-27 23:23:33 +00:00
reality
83a37a88f9 o dats coo 2013-08-27 22:52:26 +00:00
reality
0ced8cf27c fix report output 2013-08-27 22:09:59 +00:00
reality
e6b764bd25 cname not channel 2013-08-27 22:08:28 +00:00
reality
78860ce01a oh jesus [#571] 2013-08-27 22:01:44 +00:00
reality
5cdd2d927c well let us see 2013-08-25 23:20:14 +00:00
reality
4a3dbd8f3f um that should do it 2013-08-25 23:09:34 +00:00
reality
ee4ee92340 314 fallback for hostmask 2013-08-25 23:04:46 +00:00
reality
d3d25164c3 change offline time getuserhose 2013-08-25 22:56:19 +00:00
reality
5de0e8ad7d apparently it was 2013-08-25 22:37:31 +00:00
reality
397b732341 could it be? 2013-08-25 22:36:06 +00:00
reality
dd7abf2fff more debugging 2013-08-25 22:32:51 +00:00
reality
fdd3187c82 idfk 2013-08-25 22:22:02 +00:00
reality
884158c27e test 2013-08-25 22:16:12 +00:00
reality
223a000c91 more debug 2013-08-25 22:14:39 +00:00
reality
1c31d46d58 debug 2013-08-25 22:11:26 +00:00
reality
51a7cbaffa i guess 2013-08-25 22:05:50 +00:00
reality
459b6917b5 sigh 2013-08-25 21:59:06 +00:00
reality
96369ab604 split on \n 2013-08-25 20:58:11 +00:00
reality
69f061c671 pick random result for ~imgur 2013-08-25 20:45:47 +00:00
reality
cb38352519 remove imgur from the search terms lol (fix regexen) 2013-08-25 19:07:11 +00:00
reality
ab9cfb1469 fix for not found 2013-08-25 19:04:42 +00:00
reality
760780537a imgur keyword search 2013-08-25 19:02:34 +00:00
reality
ec5ef85023 fucking dumbass 2013-08-25 16:13:07 +00:00
reality
ecd30eb896 forgot a bind..... 2013-08-25 16:10:43 +00:00
reality
5cf79312f4 some more efficiency improvements in users 2013-08-25 15:37:32 +00:00
reality
31f32ca8da performance enhancements to resolveUser [Close #570] 2013-08-25 14:56:00 +00:00
reality
36aae7cad1 timer 2013-08-24 23:11:34 +00:00
reality
f664ba5e5f lol 2013-08-24 23:06:53 +00:00
reality
103407634d counters for channels too 2013-08-24 20:55:57 +00:00
reality
9a4111c393 ~mergeusershook for notify 2013-08-24 20:42:30 +00:00
reality
dfde53b8ac fix the host matching thing and make the regex sexier 2013-08-24 20:27:44 +00:00
reality
abee98b68d revere time order for notifies 2013-08-24 19:53:10 +00:00
reality
14b1727122 didnt mean to push that yet 2013-08-24 19:42:34 +00:00
reality
a6ff79e5cd fix missing entry link 2013-08-24 19:39:02 +00:00
reality
55ff01a618 save before reload 2013-08-24 19:19:58 +00:00
reality
a10a6bf9e6 that should do it 2013-08-24 19:08:43 +00:00
reality
2ab019008f whoops 2013-08-24 19:05:01 +00:00
reality
5358d1be96 thatshoulddo it 2013-08-24 19:03:13 +00:00
reality
2263f884f0 removedebug 2013-08-24 18:59:43 +00:00
reality
e56eaa7a9f debug 2013-08-24 18:56:23 +00:00
reality
08b46b9a8b fixthe entry issuething 2013-08-24 18:54:42 +00:00
reality
de54ec5c61 [close #569] 2013-08-24 18:32:52 +00:00
reality
c397ba40f4 run next anyway 2013-08-24 17:58:17 +00:00
reality
83ffee2874 1 not 0 2013-08-24 17:56:54 +00:00
reality
570239cccf whoopsies 2013-08-24 17:56:11 +00:00
reality
3e8ba74459 view notifies by user [#568] 2013-08-24 17:53:16 +00:00
reality
ec72489300 do [#568] 2013-08-24 17:39:04 +00:00
reality
16607a68d2 revert notifies changes 2013-08-24 15:05:40 +00:00
reality
5b571a0cb8 another test 2013-08-24 15:04:27 +00:00
reality
51e5f620bf test 2013-08-24 15:02:48 +00:00
reality
779ace09bf search by user & remove debug output 2013-08-24 14:49:19 +00:00
reality
1d73115c33 search box for the notificatons [close #563] 2013-08-24 14:46:38 +00:00
reality
904b7d22d5 order notifies right [close #567] 2013-08-24 14:32:27 +00:00
reality
13ff92899c Merge branch 'master' of github.com:reality/dbot 2013-08-24 13:56:53 +00:00
reality
405b3d47e4 Create addIndexLink api func for web to link to index not based on module name. Correct titles for notifications + bans. Also hopefully fix the fineWebPerms access for PUs/Mods [close #565] 2013-08-24 13:56:45 +00:00
reality
a40abd4bbd and trim it 2013-08-24 13:31:12 +00:00
reality
4f4cdea951 this thing 2013-08-24 13:30:17 +00:00
reality
7eec11197a thingy thingy 2013-08-24 13:28:46 +00:00
reality
165c9491a9 herpo derpo 2013-08-21 21:44:10 +00:00
reality
1ff9718039 coloiurs and format change for ~report 2013-08-21 21:10:06 +00:00
reality
91d6f64520 whoops 2013-08-21 20:38:51 +00:00
reality
a5eda46339 some fixes for punctuation 2013-08-21 19:57:19 +00:00
reality
cc52b81eb2 there we go 2013-08-21 19:51:41 +00:00
reality
7bbea38454 fuck youuuuuuu 2013-08-21 19:32:17 +00:00
reality
f3e18f63bb i think that should do it 2013-08-21 19:30:01 +00:00
reality
6d4291c564 fixy fixy 2013-08-21 19:28:33 +00:00
reality
66ead26635 cool if it works 2013-08-21 19:26:45 +00:00
reality
18d67e0f26 space | $ 2013-08-21 19:18:00 +00:00
reality
dee39dd14a derp 2013-08-21 19:16:23 +00:00
reality
fc345f4ebc colour tags 2013-08-21 19:14:55 +00:00
reality
46231c9e56 colours for the type thing 2013-08-21 19:10:10 +00:00
reality
73ca19ca73 dont use coloured strings as db keys lololo 2013-08-21 18:34:31 +00:00
reality
0bcf220d91 fully qualified colours link 2013-08-21 18:32:12 +00:00
reality
e5818e2f04 fix 2013-08-21 18:26:36 +00:00
reality
ddc4b099ee t:wqMerge branch 'master' of github.com:reality/dbot 2013-08-21 18:12:51 +00:00
reality
493f29ff57 colours for ~notify [#560] 2013-08-21 18:12:43 +00:00
Luke Slater
15d5c1ce16 Merge pull request #561 from kabniel/patch-1
Update link.js
2013-08-21 10:37:54 -07:00
kabniel
e34b46d4e4 Update link.js
change title regex to be non-greedy
2013-08-21 19:24:04 +02:00
reality
509911aae0 reset that shit 2013-08-21 15:38:43 +00:00
reality
a9fdd82911 how about this 2013-08-21 15:32:32 +00:00
reality
4d130df390 mroe thingy 2013-08-21 15:27:30 +00:00
reality
284a316cd5 thing 2013-08-21 15:26:16 +00:00
reality
fc4537bcea debugging 2013-08-21 15:22:05 +00:00
reality
0efa8d0217 that might do it 2013-08-21 15:18:08 +00:00
reality
2c988b0f77 i love shots in the dark 2013-08-21 15:13:58 +00:00
reality
71b7b3c570 that might do it 2013-08-21 15:11:06 +00:00
reality
f2755468e0 reality is a dumbass 2013-08-21 14:58:43 +00:00
reality
506ca60682 onyl accept ~ri images bigger than 300x300 2013-08-21 14:55:44 +00:00
reality
d71906838d change notify output format [#560] 2013-08-19 18:21:10 +00:00
reality
e1c8966d9f missing bind 2013-08-19 18:00:56 +00:00
reality
1d5f635f24 werent clearing pre-emit hooks on reload DUMBASS 2013-08-19 17:57:02 +00:00
reality
74ec643208 save debug 2013-08-19 17:51:55 +00:00
reality
a7b2ba96e7 remove extra JOIN listener in users. derp 2013-08-19 17:32:19 +00:00
reality
0f53693c28 implement rUser cache [#559] 2013-08-19 17:11:07 +00:00
reality
5b82ab8690 double derp 2013-08-19 16:57:19 +00:00
reality
68902d74bd derp 2013-08-19 16:54:11 +00:00
reality
c86dc4035b update jsbot for the thingy thing 2013-08-19 16:50:52 +00:00
reality
fea9932631 re-add new_channel_user event in new user tracker (derp) 2013-08-19 08:28:40 +00:00
reality
9a5a75c1c2 set requireweblogin for bans 2013-08-18 20:31:03 +00:00
reality
0739997a59 thingy thiny 2013-08-18 20:28:31 +00:00
reality
fe6141ea81 web part for ban list [#557] 2013-08-18 20:23:13 +00:00
reality
5233481992 dont store bans in quotes, store ban records [#557] 2013-08-18 20:10:19 +00:00
reality
239e94fe05 automatically post version on greload and fix removealias bug 2013-08-18 19:55:06 +00:00
reality
74558aea20 rewrite nick tracking basically, remove a bunch of unused shite [#537] 2013-08-18 19:36:53 +00:00
reality
e04ffa5f25 dope 2013-08-18 17:46:57 +00:00
reality
c513e8cd33 ignore certain commands for log [#556] 2013-08-18 17:42:23 +00:00
reality
e5c51682fb fine tuned web permissions [close #553] 2013-08-18 17:32:57 +00:00
reality
45eb778560 derp 2013-08-18 16:39:35 +00:00
reality
930ca1fbc0 missing log and custom log messages [close #555] 2013-08-18 16:37:30 +00:00
reality
403fd035a7 notify upgrades and whatnot 2013-08-18 15:19:15 +00:00
reality
656861f6df update jsbot for jsbot/#14 fix 2013-08-17 21:28:03 +00:00
reality
0d927881b4 do [close #552] 2013-08-17 21:04:42 +00:00
reality
da025dafbb ability to supple reason with ~quiet [#551] 2013-08-17 19:52:07 +00:00
reality
fa1634d040 unquiet notifies 2013-08-17 19:19:09 +00:00
reality
de8285e199 fix getChannel references 2013-08-17 19:07:48 +00:00
reality
152db6995f add notifications for quiet [close #550] 2013-08-17 19:01:05 +00:00
reality
6fb7c8e91f fix the quote/command correct order thing 2013-08-17 18:13:38 +00:00
reality
52d38aa1e7 create ~removealias command [Close #549] 2013-08-17 17:23:43 +00:00
reality
9d6b2cc3e1 fix ~mergeusers, create getChannel and resolveChannel distinction [#548] 2013-08-17 17:09:55 +00:00
reality
06053b9e17 update currentNick in event pre-emit [close #547] 2013-08-17 16:35:57 +00:00
reality
897b27f31e whatever 2013-08-13 18:30:25 +00:00
reality
98782fed57 update jsbot 2013-08-13 18:29:05 +00:00
reality
e086afc4d8 update jsbot 2013-08-13 18:14:01 +00:00
reality
f6c1f22b4f prevent multiple notifies for missing messages 2013-08-13 17:53:30 +00:00
reality
745a763b7f return after giving command suggestion 2013-08-12 23:32:23 +00:00
reality
7517540cc5 derp 2013-08-12 23:18:40 +00:00
reality
0a212bab1d some command correction shiz 2013-08-12 23:14:44 +00:00
reality
2ed6488d77 derp 2013-08-12 22:25:41 +00:00
reality
e757ee34df fix web routes 2013-08-12 22:14:14 +00:00
reality
a3d18884aa remove a bunch of debugging output 2013-08-12 21:59:38 +00:00
reality
154a0b30fe Modified missing report system as per [#545] 2013-08-12 21:58:30 +00:00
reality
e06c1647c4 fix ~warnings output 2013-08-12 17:17:38 +00:00
reality
3136db5cb4 fix youtube issue 2013-08-11 17:33:47 +00:00
reality
b7ccc8c0e6 even betterer 2013-08-07 19:17:30 +00:00
reality
4dd6fab12f more youtube debugging 2013-08-07 19:11:07 +00:00
reality
bc23d64686 bleh 2013-08-05 22:48:51 +00:00
reality
c0865b1bea increase notify delay? 2013-08-05 22:33:10 +00:00
reality
eb0a61c25b fix offline notifies 2013-08-05 22:18:47 +00:00
reality
99eb1462ad youtube debug output 2013-08-05 22:11:25 +00:00
reality
e9c6729894 remove trailing spaces from report reasons 2013-08-05 19:51:38 +00:00
reality
bb3d846cad remove process.nextTick 2013-08-05 17:41:20 +00:00
Luke Slater
30a371d4d5 Merge pull request #541 from reality/weblogin
Weblogin
2013-08-05 10:34:59 -07:00
Luke Slater
9befd818d5 more efficient regex code 2013-08-05 16:03:30 +00:00
Luke Slater
8ca4796295 fix the thingy whatsit (good commit message eh) 2013-08-05 15:58:39 +00:00
Luke Slater
36da81d003 Merge pull request #539 from agjmills/master
fixed bug with ACTION, replaced with users name
2013-08-05 08:56:10 -07:00
Alexander Mills
12c7721ef5 fixed bug with ACTION, replaced with users name 2013-08-05 16:53:29 +01:00
reality
450ffce0e2 stagger pend notifies 2013-08-03 01:53:36 +00:00
reality
9a99d5eb47 fix up report for use with login 2013-07-29 21:08:41 +00:00
reality
21b2b4eec3 i dont have a clue what even fucking fixed that 2013-07-29 21:04:12 +00:00
reality
1b50a3583c fix the whatsit 2013-07-29 20:50:48 +00:00
reality
b069ce4b0d fix more redirects 2013-07-29 20:45:35 +00:00
reality
329b45e895 redirect not re-render upon failed auth 2013-07-29 20:44:12 +00:00
reality
70f41df08a more thing 2013-07-29 20:36:27 +00:00
reality
2c6729a7f4 thing 2013-07-29 20:33:13 +00:00
reality
13334e3b4d each 2013-07-29 20:25:07 +00:00
reality
abfcee0e48 idk 2013-07-29 20:16:53 +00:00
reality
0b087e2f7b loginform 2013-07-29 20:14:43 +00:00
reality
652a9ef7a3 web login works, with access settings for certain modules [#538] 2013-07-29 20:08:25 +00:00
reality
78b9bf2525 dope 2013-07-29 19:12:16 +00:00
reality
5214feba00 OH BABY [#538] 2013-07-29 19:03:24 +00:00
reality
036b926b28 fix encoding for define 2013-07-28 21:26:04 +00:00
reality
3788aa9399 it fucking works (web login that is) [#538] 2013-07-28 18:11:10 +00:00
reality
ea9d3ee0ff only append period if it doesnt already exist 2013-07-28 16:26:54 +00:00
reality
914e5677b8 Full set of Italian translations from gian-maria.daffre@giammi.com 2013-07-28 12:23:06 +00:00
reality
b1916d6043 missing data fix for youtube 2013-07-28 10:41:08 +00:00
reality
e3b35adb1c ah just remove that shit for now 2013-07-27 23:11:02 +00:00
reality
ba9921919f fix imgur config pointer 2013-07-27 23:08:32 +00:00
reality
12e11e78c1 some other stuff and the login view. there is some stupid issue picking up the credentials from the form though idk 2013-07-27 18:14:00 +00:00
reality
f53b826307 login and logout web routes [#538] 2013-07-27 17:31:00 +00:00
reality
d1d62be6f2 basic skellington for web login stuff [#538] 2013-07-27 17:19:53 +00:00
reality
fe965049f9 fix ctcp string 2013-07-26 17:34:37 +00:00
reality
dbbe33f965 dope 2013-07-26 17:03:52 +00:00
reality
dfaa795b8f put eachseries in process.nextTick 2013-07-26 17:01:22 +00:00
reality
ac8783dbd6 dope 2013-07-26 16:59:22 +00:00
reality
b5c320a1b2 users output and jsbot hour 2013-07-26 16:57:21 +00:00
reality
a99a421767 mods can run pu commands 2013-07-26 11:59:37 +00:00
reality
b54a5a5ccc oh fuck 2013-07-26 11:54:39 +00:00
reality
891812ba36 unnecessary currentNick 2013-07-26 11:53:30 +00:00
reality
ea11ed5ac6 set power_user access in quiet specifically 2013-07-26 11:46:57 +00:00
reality
ae31b121d8 wat 2013-07-25 23:22:47 +00:00
reality
4ae10a2b26 link handlers callback result instead of event.reply it[Close #536] 2013-07-25 21:56:44 +00:00
reality
ac2d010a57 start 0.5 dev 2013-07-25 21:50:29 +00:00
reality
48a0187c0d change VERSION 2013-07-25 18:36:41 +00:00
reality
516ede704b upgrade getting started instruction [#352] 2013-07-25 18:30:50 +00:00
reality
df43d580a7 fix install.sh 2013-07-25 18:18:11 +00:00
reality
bad2662081 link for ~youtube (lol) [#534] 2013-07-25 17:16:57 +00:00
reality
26eebdab98 fix youtube search [#543] 2013-07-25 17:07:00 +00:00
reality
55d8e9257e syntax error 2013-07-24 22:48:35 +00:00
reality
f882d16313 urgh 2013-07-24 22:45:57 +00:00
reality
827e27bed9 fix 2013-07-24 22:42:02 +00:00
reality
8e9a6e5c8e fix 2013-07-24 22:38:52 +00:00
reality
302023e14e thing 2013-07-24 22:35:46 +00:00
reality
0c6fdf826f output in setconfig fix 2013-07-24 22:33:03 +00:00
reality
9bc4128e3a fix setconfig 2013-07-24 22:31:04 +00:00
reality
8dd2a6a97c setconfig prefix modules [#520] 2013-07-24 22:27:50 +00:00
Luke Slater
aa40c78127 Merge pull request #535 from reality/database
Merge Database Branch to Master
2013-07-24 14:42:52 -07:00
reality
79eaf8c56e fix youtube again 2013-07-24 18:06:39 +00:00
reality
879bbf63b5 fix youtube 2013-07-24 18:02:06 +00:00
reality
a1a292846d dumbass 2013-07-19 20:20:59 +00:00
reality
f2d93d2f18 youtube search 2013-07-19 20:15:50 +00:00
reality
cd93987919 ok this should do it 2013-07-15 19:30:00 +00:00
reality
2c2b501c73 thing 2013-07-15 19:19:17 +00:00
reality
9dea85730d youtube link handle thing [#534] 2013-07-15 18:52:40 +00:00
reality
d9d7d9bff7 fix the things 2013-07-15 18:51:32 +00:00
reality
2203f50dea testing version of [#530] 2013-07-14 14:55:15 +00:00
reality
08843950dd yee [#531] 2013-07-14 13:25:11 +00:00
reality
b86987dc48 wat 2013-07-14 10:58:59 +00:00
reality
2bdfc55879 ffs 2013-07-14 10:55:08 +00:00
reality
9abecc6232 derp [#533] 2013-07-14 09:50:51 +00:00
reality
1171637e42 Merge branch 'database' of github.com:reality/depressionbot into database 2013-07-14 09:29:36 +00:00
reality
f90a1b97b4 if user JOIN channel with !currentNick, update [#532] 2013-07-14 09:29:22 +00:00
Luke Slater
8b436905b8 Merge pull request #529 from iceTwy/database
Last string translated to French
2013-07-11 12:43:21 -07:00
iceTwy
4fbbe39e79 the LAST fr string 2013-07-11 21:40:46 +02:00
Luke Slater
73529a0c1f Merge pull request #528 from iceTwy/database
French translation should now be completely accurate
2013-07-11 12:27:16 -07:00
iceTwy
b54070d7b3 fixed wrong translation string locale 2013-07-11 21:24:30 +02:00
iceTwy
1f7c247b94 add French translation 2013-07-11 21:21:23 +02:00
iceTwy
0dd7d03850 fun French strings are even funnier now 2013-07-11 21:19:34 +02:00
iceTwy
d673b9c8ec major mess-up fixed; missing translation for a string added 2013-07-11 21:12:29 +02:00
iceTwy
3944906de4 holla at dem people in Aberystwyth, name of the league translated to French 2013-07-11 21:08:43 +02:00
Luke Slater
c63c78e086 Merge pull request #526 from iceTwy/database
French translation for github module & fixed typos
2013-07-11 10:42:25 -07:00
iceTwy
ad76a7b12d Fixed typos in French translation 2013-07-11 17:51:49 +02:00
iceTwy
91a121536c Updated French translation for github module 2013-07-11 17:48:16 +02:00
iceTwy
7401dc0925 French translation 2013-07-11 17:46:26 +02:00
reality
68e0688e63 t pushMerge branch 'database' of github.com:reality/depressionbot into database 2013-07-11 15:32:31 +00:00
reality
a5d02d19ff add github as reg 2013-07-11 15:25:45 +00:00
reality
b677986c68 yeah 2013-07-11 15:24:19 +00:00
reality
9379b73bdf thing 2013-07-11 15:22:29 +00:00
Luke Slater
da801cc72f Update strings.json 2013-07-11 15:11:25 +00:00
Luke Slater
e1b15b7376 Update strings.json 2013-07-11 02:49:36 +00:00
Luke Slater
3759b7b327 fix admin str err 2013-07-11 02:46:13 +00:00
Luke Slater
8e46b21475 Merge pull request #525 from iceTwy/database
French translations for everything
2013-07-10 19:44:37 -07:00
iceTwy
b933981859 French translation 2013-07-11 04:40:05 +02:00
iceTwy
519b7ca7b0 French translation 2013-07-11 04:38:10 +02:00
iceTwy
9c73342176 French translation 2013-07-11 04:34:47 +02:00
iceTwy
4b3d88ecb0 French translation 2013-07-11 04:32:10 +02:00
iceTwy
9faee2c71a French translation 2013-07-11 04:30:58 +02:00
iceTwy
878d3b29fb French translation 2013-07-11 04:30:09 +02:00
iceTwy
0fed8c9923 French translation 2013-07-11 04:27:31 +02:00
iceTwy
46d2415c2d French translation 2013-07-11 04:23:43 +02:00
iceTwy
f753e6cb83 French translation 2013-07-11 04:18:49 +02:00
iceTwy
97a35bb43b French translation 2013-07-11 04:08:26 +02:00
iceTwy
15113ee2b1 French translation 2013-07-11 03:59:30 +02:00
iceTwy
02164ab2a7 French translation 2013-07-11 03:51:01 +02:00
iceTwy
86ff430169 French translation 2013-07-11 03:48:52 +02:00
iceTwy
55c48bf8b0 French translation 2013-07-11 03:48:07 +02:00
iceTwy
09dbe74662 French translation 2013-07-11 03:46:15 +02:00
iceTwy
e29927b478 French translation 2013-07-11 03:29:02 +02:00
iceTwy
2b8f1e4a92 French translation 2013-07-11 03:27:11 +02:00
iceTwy
5e4199b736 French translation 2013-07-11 03:16:52 +02:00
iceTwy
12a2ae0728 French translation 2013-07-11 03:13:34 +02:00
iceTwy
c7c5fbb4ef French translation 2013-07-11 03:08:54 +02:00
iceTwy
2beb87f86f French translation 2013-07-11 02:48:35 +02:00
reality
7eeb687385 doh 2013-07-09 21:16:41 +00:00
reality
8688ee05ba soundcloud command [#524] 2013-07-09 21:08:55 +00:00
reality
291bff50da soundcloud module [#524] 2013-07-09 19:17:48 +00:00
reality
62871dc80e jimble command 2013-07-08 11:02:27 +00:00
reality
287b718b17 fuck 2013-07-08 10:06:34 +00:00
reality
9aec9f4df4 req params channel 2013-07-06 18:52:31 +00:00
reality
299aafea87 dbType redis 2013-07-06 18:51:03 +00:00
reality
a42271dcf9 connections not servers lol 2013-07-06 18:49:34 +00:00
reality
7e1818d875 update report slow 2013-07-06 18:47:47 +00:00
reality
c5448080bf record notifies 2013-07-06 18:45:21 +00:00
reality
7dfa493f44 fix nunban 2013-07-06 18:00:34 +00:00
reality
134f2b76bb fix web link api call for ~link 2013-07-04 23:20:09 +00:00
reality
eec997a0ac whoops 2013-07-04 22:46:03 +00:00
reality
b5d286b86e jawohl 2013-07-04 22:44:19 +00:00
reality
6c3f3119ff blah 2013-07-04 22:42:37 +00:00
reality
53defaaeea wtf 2013-07-04 22:37:34 +00:00
reality
f105afad17 test 2013-07-04 22:36:37 +00:00
reality
a821547838 fix addquote 2013-07-04 22:32:56 +00:00
reality
b6a56e23f6 fix nickserv auth 2013-07-04 22:29:52 +00:00
reality
6efc01e90a Merge https://github.com/reality/dbot into database 2013-07-03 14:17:43 +00:00
reality
c1a63d331a auto modules prefix in ~showconfig [#520] 2013-06-30 18:25:45 +00:00
reality
1d9c7fd40e remove config directive for admin channel in kick 2013-06-30 17:22:38 +00:00
reality
2c2e1aefa2 kick uses root admin_channel directive [#513] 2013-06-30 17:22:16 +00:00
reality
fee7fedbf7 fix the project quotes thing 2013-06-30 15:40:47 +00:00
reality
8dcde52099 few small jimblings 2013-06-30 15:11:56 +00:00
reality
d650f2a10a remove stats from db branch 2013-06-27 22:33:44 +00:00
reality
1aa1800ea2 finish off auto resolve 2013-06-27 19:19:13 +00:00
reality
6faedb59a8 fix report [#511] 2013-06-27 19:16:18 +00:00
Sam Nicholls
08d5f15679 Fix missing username 2013-06-27 19:55:45 +01:00
reality
72200596de reinstate ~profile command 2013-06-27 18:43:52 +00:00
reality
dd64b5955a fix ~help module thing 2013-06-27 18:28:35 +00:00
reality
7e2b717d0a poll uses event.rUser [#511] 2013-06-27 18:26:54 +00:00
reality
f924686871 Merge github.com:reality/dbot into database 2013-06-27 18:13:11 +00:00
reality
e1629f3a16 Alias support for command.api.hasAccess [#515][#514][#511] 2013-06-27 16:51:32 +00:00
reality
68b0977bae ignore uses event.rUser [#511][#514] 2013-06-27 15:33:18 +00:00
reality
3021601c52 fix quotes 2013-06-27 15:26:21 +00:00
reality
4ffff09381 Rewrite warning module for databank [#508] 2013-06-23 11:37:01 +00:00
reality
fe76718780 update jsbot 2013-06-22 20:46:17 +00:00
reality
a65c96138e fix a bunch of shit 2013-06-22 20:23:47 +00:00
reality
39db5423df finish users rewrite 2013-06-22 17:19:04 +00:00
reality
df1404b3ae dont pass channel info to createUser 2013-06-22 16:32:18 +00:00
reality
66f5b1df43 rewrite JOIN users listener 2013-06-22 16:25:31 +00:00
reality
b3b91f189f Draft of new users listener [#511][#480] 2013-06-22 15:22:23 +00:00
reality
bfd11c5d4d fix showconfig recursion 2013-06-22 14:37:21 +00:00
reality
520be40504 rChannel [#507] 2013-06-21 18:40:00 +00:00
reality
5f3c06a7a0 merge 2013-06-21 18:32:00 +00:00
reality
efe54b5e35 event.rUser contains resolved user object from users module [#507] 2013-06-21 18:11:22 +00:00
reality
96a566290d update jsbot 2013-06-21 17:55:29 +00:00
reality
77af2a1250 meeeeeeerge 2013-06-13 19:11:42 +00:00
reality
b201c1aaad fix profile config pointers 2013-06-13 18:59:14 +00:00
reality
9093a69907 auto reload on setconfig [#489] 2013-06-05 22:59:37 +00:00
reality
9927f7add3 update github 2013-06-05 22:47:13 +00:00
reality
f3fda2b696 Merge git://github.com/reality/dbot into database 2013-06-05 22:15:56 +00:00
reality
7592a6caa4 pushconfig operational [#489] 2013-06-05 22:15:17 +00:00
reality
815d7a39cd setconfig working + msg if new key is being created [#489] 2013-06-05 21:52:14 +00:00
reality
546ce64707 admin.internalAPI.setConfig operational [#489] 2013-06-05 21:41:20 +00:00
reality
97907603f5 automatically save module load changes [#489] 2013-06-05 21:14:21 +00:00
reality
b7a3b6a139 save a seperate customconfig so not everything is saved to config.json. create saveconfig internal api function for admin [#489] 2013-06-05 21:00:52 +00:00
reality
eafc2dbee1 fix config pointers in admin and imgur [#489] 2013-06-05 20:13:40 +00:00
reality
5879baeff5 missing usage 2013-06-05 20:12:52 +00:00
reality
b77644d1d4 Fixes for config path in some place [#489] 2013-06-04 00:10:12 +00:00
reality
a25620bf9e recursively call showconfig [#489] 2013-06-04 00:06:41 +00:00
reality
4a7fcd57b3 Module config now loaded from config.json , rleloaded upon reloading and various module changes to make it work right [#474] [#489] 2013-06-03 23:00:23 +00:00
Sam Nicholls
2471e4bca3 Possible project page anniversary remake 2013-06-01 20:33:04 +02:00
Sam Nicholls
5ff5c8a464 Possible project page fix finale 2013-06-01 20:30:53 +02:00
Sam Nicholls
94e9355e7c Possible project page fix reprise 2013-06-01 20:15:29 +02:00
Sam Nicholls
adc4f5c710 Possible project page fix 2013-06-01 20:13:43 +02:00
reality
ec0c4ad781 merge of terror #2 2013-06-01 17:57:07 +00:00
reality
b4581b1995 remove extra head 2013-06-01 15:55:48 +00:00
reality
a01438a879 worst merge 2013 eu 2013-06-01 15:55:09 +00:00
reality
150821cbb3 fix db pointer for imgur olDB 2013-05-28 17:40:25 +00:00
reality
3726be64b7 yee 2013-05-27 17:48:36 +00:00
reality
429eafd8e4 banOutput option in command [#460] 2013-05-27 17:45:30 +00:00
reality
e1ea156a41 merge udFallback into database branch [#477] 2013-05-27 17:33:10 +00:00
reality
7e4ae2460a Automatic callback for ~ajs [#476] 2013-05-26 20:24:05 +00:00
reality
e7605e0c0e Merge git://github.com/reality/depressionbot into database 2013-05-26 17:20:49 +00:00
reality
1bb266d23a updat readme main install instructions 2013-05-26 15:55:20 +00:00
reality
d8191c8232 Update install.sh modules and update web docs [#464][#351] 2013-05-26 15:49:44 +00:00
reality
1ce4b05932 documentation for the spotify module 2013-05-26 15:38:48 +00:00
reality
bc7bac1218 Do not continue to load module if data file syntax error occurs [#466] 2013-05-26 15:21:13 +00:00
reality
3148b3e434 document new command config features [#467][#351] 2013-05-26 14:16:56 +00:00
reality
9847a05301 Add accessOutput command to tell users when they are not authorised to run a command [#467] 2013-05-26 14:14:01 +00:00
reality
d9850d19d5 fix some more mergeuser issues [#470] 2013-05-26 13:29:21 +00:00
reality
f69f999118 fix various mergeusers hooks [#472] 2013-05-26 13:11:09 +00:00
reality
5dddae4f00 mergeChannelUsers internal API function in users + mergeusers seems to be working [#470] 2013-05-26 12:37:37 +00:00
reality
2fc5fc6992 remove command hooks [#471] 2013-05-25 22:09:07 +00:00
reality
5bf6088453 fix command emit on reload 2013-05-25 21:34:11 +00:00
reality
b71c9e4504 link dependency for status 2013-05-25 21:06:32 +00:00
reality
712db49274 Merge github.com:reality/depressionbot into database 2013-05-25 21:05:45 +00:00
reality
61bd1312a6 Fix fucking async hell and add getAllChannels 2013-05-21 20:17:22 +00:00
reality
e8757347ba eventsdocumentation in users [#351] 2013-05-21 18:39:11 +00:00
reality
a140c19483 blue link 2013-05-21 18:32:59 +00:00
reality
66cd7b757a Merge github.com:reality/depressionbot into database 2013-05-21 17:48:42 +00:00
reality
77eec1e07f merge 2013-05-21 17:47:02 +00:00
reality
a446999285 fix merge properly 2013-05-21 17:32:26 +00:00
reality
eb4e788b5c fix merge 2013-05-21 17:31:01 +00:00
reality
11b23ffc85 fix for the bug with infostring i introduced fixing undefinedxundefined 2013-05-21 16:05:20 +00:00
reality
90d34f3aa4 Merge github.com:reality/depressionbot into database 2013-05-21 15:59:21 +00:00
reality
6d9f3b644c fix ~rmdeny and add web route /quoteremovals [#455] 2013-05-20 19:51:09 +00:00
reality
0bc0a1bdb7 quote add for db branch in imgur 2013-05-20 15:40:13 +00:00
reality
48ce88490d Merge github.com:reality/depressionbot into database 2013-05-20 15:35:42 +00:00
reality
b3d2b89734 Merge github.com:reality/depressionbot into database 2013-05-20 15:27:22 +00:00
reality
388d51278d Merge github.com:reality/depressionbot into database 2013-05-20 15:25:21 +00:00
reality
4e53a06e75 Merge github.com:reality/depressionbot into database 2013-05-20 15:05:30 +00:00
reality
3541534b76 this should fix [#453] 2013-05-19 09:52:14 +00:00
reality
449ad684ad More quotes docs updates [#351] 2013-05-17 17:57:21 +00:00
reality
e8c2db5488 Update documentation for users [#351] 2013-05-17 17:23:39 +00:00
reality
5bcd1d9c27 remove chancein 2013-05-17 17:04:55 +00:00
reality
6dfa5de478 youare doesnt need snippets [#135] 2013-05-17 17:04:19 +00:00
reality
1e52809e06 nickserv thing 2013-05-17 16:57:47 +00:00
reality
ffec54ffe2 reload 2013-05-17 16:33:04 +00:00
reality
df2b484a66 merge 2013-05-17 13:32:41 +00:00
reality
33f8b21edd config rather than currentOption 2013-05-17 12:02:38 +00:00
reality
9d03364a23 merge [#439] 2013-05-17 07:40:46 +00:00
reality
eac0083bea Build help link automatically [#439] 2013-05-17 07:34:25 +00:00
reality
cb0956405f Merge git://github.com/reality/depressionbot into database 2013-05-17 07:01:29 +00:00
reality
ccc962d9f2 update admin docs [#351] 2013-05-10 18:38:57 +00:00
reality
41ec896dfc Merge git://github.com/reality/depressionbot into database 2013-05-10 18:13:41 +00:00
reality
0259584c25 savemodules command [#438] 2013-05-10 18:12:40 +00:00
reality
e8537a93b2 Remove leading slash in url api maker [#435] 2013-05-06 20:09:19 +00:00
reality
5b0f4d3ae8 finish off poll using new users api [#434] 2013-05-06 20:00:31 +00:00
reality
75a909df64 Poll web interface now working [#420] 2013-05-06 19:43:14 +00:00
reality
33b9b8d1b0 poll web list works [#420] some commands using new users [#434] 2013-05-06 18:12:25 +00:00
reality
9db515d44a Fix [#433] 2013-05-06 15:53:42 +00:00
reality
090f15e738 remove unecessary code from module loading, fix [#432] 2013-05-06 15:36:35 +00:00
reality
ae22060fcb Merge git://github.com/reality/depressionbot into database 2013-05-06 15:02:23 +00:00
reality
da5e79ebeb Efficiency improvements in users, return of isKnownUser API function [#331] 2013-05-02 18:25:10 +00:00
reality
e426f4fae9 bump github 2013-05-01 19:53:37 +00:00
reality
9cf6769da5 Merge git://github.com/reality/depressionbot into database 2013-04-30 19:36:44 +00:00
reality
22704a2158 move dbot.cleanNick to quotes.internalAPI.cleanRef [#270] 2013-04-30 17:19:23 +00:00
reality
b08e12560f merge earlier 2013-04-30 17:10:21 +00:00
reality
4891b70ec3 merge [#307] 2013-04-30 16:47:47 +00:00
reality
7c31d5bbe8 Remove a bunch of useless users API functions, finish documentation [#352] 2013-04-30 14:04:21 +00:00
reality
88c51209af mergy mergy 2013-04-30 13:53:16 +00:00
reality
40583ed7a3 bump github 2013-04-24 20:49:44 +00:00
reality
9625f1d316 merge with master, command uses nickserv auth in db [#421] 2013-04-24 20:45:20 +00:00
reality
9f211c4da0 Module and API function to check nickserv authentication. [#421] 2013-04-23 18:27:25 +00:00
reality
639022fa55 Merge github.com:reality/depressionbot into database 2013-04-23 17:28:50 +00:00
reality
41f4a830b2 Fix quotes web component [Close #419] 2013-04-23 17:26:44 +00:00
reality
cca4fadc42 Merge git://github.com/reality/depressionbot into database 2013-04-22 19:37:44 +00:00
reality
f98f7e435a that should be all of the dependencies [#413] 2013-04-22 16:20:17 +00:00
reality
099d278cbc dont add quotes that already exist [#331] 2013-04-22 15:50:05 +00:00
reality
f905c58877 Fix setconfig, showconfig and pushconfig from being confused by false values [#331] 2013-04-22 14:46:30 +00:00
reality
5eba864f22 fix imgur for now 2013-04-22 14:38:03 +00:00
reality
8e8953999d Various database branch fixes [#331]:
* Admin module doesn't try to use reload string when it's not there.
* Fix dent event hookin
* Fix quote retrieval (two ~q definitions and no false check before interpolate)
* Change databankerised modules to use redis for testing
2013-04-22 14:22:35 +00:00
reality
c5fb52a4a7 Merge git://github.com/reality/depressionbot into database 2013-04-21 16:23:55 +00:00
reality
840f110317 Merge pull request #403 from SamStudio8/database
Profile onLoad check [#331][Close #398]
2013-04-21 08:13:27 -07:00
Sam Nicholls
0ccd0c6301 Profile onLoad check [#331][Close #398] 2013-04-21 16:10:24 +01:00
reality
65b410416c Module loader properly iterates all automatically loaded dependencies [#399] 2013-04-21 14:51:59 +00:00
reality
420d40c848 Merge pull request #400 from SamStudio8/database
Check getProfile read was successful
2013-04-21 07:31:36 -07:00
Sam Nicholls
3130350f58 Check getProfile read was successful 2013-04-21 15:27:08 +01:00
reality
5aaa9f8856 additional channels are added to user records from 366 event [#331] 2013-04-21 14:17:29 +00:00
reality
0d76ce4166 switch users to use redis driver [#331] 2013-04-21 14:11:35 +00:00
reality
f3681953ed Merge pull request #395 from SamStudio8/database
Initial databankerisation of profile [#331]
2013-04-20 16:34:18 -07:00
Sam Nicholls
ab0a110a8e Initial databankerisation of profile [#331]
* Stats functionality disabled until completion of SamStudio8/dbot-stats#98
* Profile grid currently only works with dbType set to memory
* Merge user functionality temporarily disabled
2013-04-20 22:51:36 +01:00
Sam Nicholls
bd2d0a8953 getUser get->read 2013-04-20 20:40:30 +02:00
reality
ecd5b4b23c getallusers external 2013-04-20 16:34:02 +00:00
reality
135b6ecbba fix users not getting pushed to chan [#390] 2013-04-20 16:28:12 +00:00
reality
3cd4513fe4 fix module loader. admin sets config keys onload. I am incredibly annoyed. [#331] 2013-04-20 16:08:34 +00:00
reality
466cb12c94 getCurrentConfig, pushconfig, showconfig and setconfig databankerised [#331] 2013-04-20 13:50:47 +00:00
reality
4319ee18e1 ~addalias command for adding non-used nicks to user alias records [#373] 2013-04-20 11:21:04 +00:00
reality
8712216948 dat merge 2013-04-20 10:51:39 +00:00
reality
5420bd846b modify data structures and fix a bunch of broken async stuff in users [#331] 2013-04-14 20:00:53 +00:00
reality
77f67d64e1 merge 2013-04-14 18:39:32 +00:00
reality
ce092b688e update ban and quiet in kick.api to use configured chanserv [#261] 2013-04-14 15:33:55 +00:00
reality
f5fb2322b1 Merge github.com:reality/depressionbot into database 2013-04-14 15:16:55 +00:00
reality
a4cb96a6a4 bump jsbot 2013-04-14 15:16:38 +00:00
reality
b31d26b912 make ~qmerge a moderator command [#347] 2013-04-13 14:59:50 +00:00
reality
3a567a35da Merge github.com:reality/depressionbot into database
Conflicts:
	modules/poll/commands.js
	modules/quotes/commands.js
2013-04-13 00:57:18 +00:00
reality
aad0b5e372 Some cleanup of quotes module postdatabank [#331] Addition of addQuote API and updated places what use it [#349] 2013-04-12 22:30:45 +00:00
reality
f17f926a3b ~qsearch can search all categories with * [#331] 2013-04-12 21:52:46 +00:00
reality
b1f450a3e1 quotes listener operational 2013-04-12 21:16:56 +00:00
reality
b8a25062b5 Interpolated quotes revived and plugged into ~q. Also a event inspecific getQuote API function implemented. [#331] 2013-04-12 21:08:11 +00:00
reality
36254c9e03 Merge git://github.com/reality/depressionbot into database 2013-04-12 19:29:03 +00:00
reality
7ceba078e2 Empty quote category records are now removed [#331][#346] 2013-04-12 19:28:23 +00:00
reality
5892bd83aa ~qmerge command [Close #347] 2013-04-12 18:20:39 +00:00
reality
0098b07670 ~qrename command to rename quote categories [Close #345] 2013-04-12 18:03:52 +00:00
reality
11dcaac44c last commit meant admin commands couldnt be run. will rethink later. 2013-04-12 17:59:51 +00:00
reality
38c18366a3 Stop command execution syntax running if line is not a command. Note [#337] was fixed a few commits ago too. 2013-04-12 17:42:11 +00:00
reality
58b58aa15f ~qadd uses only save rather than save|create [#331] 2013-04-12 17:33:13 +00:00
reality
23dace4257 update ignore to use save instead of save|create [#331] 2013-04-12 17:30:56 +00:00
reality
b376a8fa54 rewrote all of quotes commands because array shims just werent good enough [#331] 2013-04-12 00:38:51 +00:00
reality
6bae0f47bf ~ignorechannel and ~unignorechannel now databankerised. Fixed bug with not initialising chan ignores onLoad. Ignore now fully databankerised. [#331] 2013-04-11 21:21:12 +00:00
reality
96a339a8d4 cleanup 2013-04-11 20:17:48 +00:00
reality
65be2ebcb5 remove useless imports from ignore api 2013-04-11 20:17:14 +00:00
reality
223b20b598 * ~ban and ~unban now fully databankerised and tested [#331]
* Refactored ~ignore and ~unignore
* Refactored API
* Command uses new ban/ignore APIs, removed its own isBanned
* Ignore is now aware of servers [#188]
2013-04-11 20:12:29 +00:00
reality
9c38316483 Merge git://github.com/reality/depressionbot into database 2013-04-11 18:19:28 +00:00
reality
53c8ca9672 Forgot to add ignore.api to last commit 2013-04-10 07:50:47 +00:00
reality
b56ac4164a isIgnoring now belongs in ignore.api, changes in command to reflect this. ~ignore now operational for commands. [#331] 2013-04-10 01:28:53 +00:00
reality
6cea1256ce thats a little better on the module loader i suppose [#331] 2013-04-10 01:07:29 +00:00
reality
384fe3024a ~ignore and ~unignore commands working on data storage/modification and listener execution prevention [#331] 2013-04-10 00:32:30 +00:00
reality
228a2611a5 Hacked up run.js so db is definitely loaded by time onLoad is run. Need to clear up 2013-04-10 00:19:56 +00:00
reality
5c48971034 Provisional onLoad and ~unignore for ignores module. Needs testing. [#331] 2013-04-09 23:16:40 +00:00
reality
9952e4583c Get user by UUID API function [#331] 2013-04-09 23:16:00 +00:00
reality
86492e3efb Merge git://github.com/reality/depressionbot into database 2013-04-09 22:55:35 +00:00
reality
14e03313ec Provisional/example ~ignore functionality using databank [#331] 2013-04-09 00:10:08 +00:00
reality
c1224a8f2c Merge git://github.com/reality/depressionbot into database 2013-03-28 22:12:43 +00:00
reality
e7be2f6b87 users module now tracks current nick, appropriate output in ~alias 2013-03-25 13:55:47 +00:00
reality
e9c44bf702 bump jsbot 2013-03-24 19:58:28 +00:00
reality
9443970c89 FIXED THAT MOTHERFUCKING BASTID BUG I AM THE RESURRECTION YEAAAAAAAAA [#272] 2013-03-24 18:05:57 +00:00
reality
17c2c4b317 Fix ~setaliasparent [#272] 2013-03-24 16:59:26 +00:00
reality
3814df98f6 users module almost fully operational with databank (few kinks in moderation commands still) [#272] 2013-03-24 16:04:01 +00:00
reality
ef9f5f2646 update js 2013-03-24 15:57:42 +00:00
reality
edcbe501e8 users onLoad and nick/join listener now databankised [#272] 2013-03-24 12:54:19 +00:00
reality
aa6a5fce42 databankise users listener, add getChannel to users api [#272] 2013-03-24 12:26:33 +00:00
reality
d30aa145aa Changed users API to databank [#272]
Behavioural changes:

* API functions no longer return values, callbacks must be submitted. These will be documented soon.
* resolveUser now returns the user record instead of just a resolved username. This means many less search operations.
* resolveUser now returns false instead of the original nick passed to it in the case of being unable to find a user.
* getServerUsers has been removed, as it is now unnecessary.
2013-03-24 11:34:52 +00:00
reality
cbc42e6fc3 Merge git://github.com/reality/depressionbot into database. Also Users API now databankerised
Conflicts:
	modules/quotes/commands.js
2013-03-24 11:09:40 +00:00
reality
71c0bdb760 all commands but ~qstats and ~rq in quotes use databank [#272] 2013-03-23 13:24:13 +00:00
reality
7bcb136e26 some initial work on users api over to databank [#272] 2013-03-22 11:44:27 +00:00
reality
4e1beb7580 Started working on transforming quotes. Need more input from evan and that before continuing I think. [#272] 2013-03-16 13:45:58 +00:00
reality
54e3b84902 Poll module now functional using databank. What of it? [#272] 2013-03-16 00:02:35 +00:00
reality
a5b65856a6 Merge git://github.com/reality/depressionbot into database 2013-03-15 23:12:30 +00:00
reality
7bb5cc722a update stats or something idk 2013-03-15 23:12:21 +00:00
reality
07f8a129d5 provisional poll thing. only commiting so i can switch branch w/e [#272] 2013-02-16 17:37:23 +00:00
reality
b288487f23 Provisional framework for database module using databank multiplexing. [#272] 2013-02-12 19:15:32 +00:00
270 changed files with 12838 additions and 2907 deletions

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
# Ignore the user config files
config.json
db.json
# ignore npm

11
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "jsbot"]
path = jsbot
url = git://github.com/reality/jsbot.git
path = jsbot
url = git://github.com/reality/jsbot.git
[submodule "modules/github"]
path = modules/github
url = git://github.com/zuzak/dbot-github.git
[submodule "modules/stats"]
path = modules/stats
url = git@github.com:SamStudio8/dbot-stats.git
path = modules/github
url = git://github.com/zuzak/dbot-github.git

View File

@ -11,18 +11,27 @@ given I started it rather a long time after I began development of the project.
Please don't judge me too harshly for this as I am, in fact, mildly allergic to
writing documentation.
Requirements:
## Getting Started
- Node JS
- [JSBot](http://github.com/reality/JSBot "JSBot"), a Javascript library which
handles the IRC protocol
- Underscore JS library
- Various modules have their own requirements also.
To get started with DBot, you first need to decide on a database system to use.
DBot uses the [databank](http://github.com/e14n/databank) library, and each
module can be configured to use any database driver databank supports in its
respective config.json file. There is currently no default database driver
option.
### External Modules
The default for all modules is the 'redis' driver, and you can simply install
the Redis server to get going.
JSBot and externally developed modules can be imported by running the following
commands in the cloned repository:
git submodule init
git submodule update
Once you have that set up, you can install DBot's dependencies, configure and
run the bot for the first time with the following command:
```
./install
```
## Upgrading
If you have used a previous version of DBot, then you can migrate most data
using the [dbot-migrate](https://github.com/reality/dbot-migrate) module.
Instructions on how to run this are included in the repository - remember to
remove db.json after migration, otherwise the instance will be slow!

View File

@ -1,5 +1,6 @@
depressionbot version 0.4-dev
dbot version 0.5-dev
this.db.search('releases', { 'name': 'jimbletron' }, function(result) { "RELEASE" });
"the database is a grilled cheese"
_.each(dbot.modules, function(module) { "RESCORE EVERYTHING" });
"He called his bot depressionbot, and that's when he was happy."

View File

@ -15,10 +15,13 @@
"admins": [ "batman" ],
"moderators": [ "whatever" ],
"power_users": [],
"moduleNames": [ "ignore", "admin", "command", "dice", "js", "kick", "quotes", "spelling", "youare", "timers", "stats", "users", "link" ],
"moduleNames": [ "ignore", "admin", "command", "dice", "js", "kick", "quotes", "spelling", "users", "youare", "timers", "sstats", "link" ],
"language": "en",
"debugMode": false,
"debugLevel": 1,
"dbType": "redis",
"redisPort": 6379,
"timezone": "Europe/London",
"repoRoot": "https://github.com/reality/depressionbot/",
"version": "Depressionbot IRC bot 0.4-dev - Lovingly crafted by The DepressionBot Foundation (a charity arm of the Official Aberystwyth Open Source International Development League)."
"version": "Depressionbot IRC bot 0.5-dev - Lovingly crafted by The DepressionBot Foundation (a charity arm of the Official Aberystwyth Open Source International Development League)."
}

33
database.js Normal file
View File

@ -0,0 +1,33 @@
var databank = require('databank'),
Databank = databank.Databank,
DatabankObject = databank.DatabankObject,
_ = require('underscore')._;
/**
* Multiplex databank objects
*/
var DatabaseDriver = function(config) {
this.config = config;
this.databank = null;
};
/**
* Connect to or create a new DataBank
*/
DatabaseDriver.prototype.createDB = function(name, driver, schema, callback) {
var params = { 'schema': schema };
if(driver == 'redis' && _.has(this.config, 'redisPort')) params.port = this.config.redisPort;
if(driver == 'disk') params.dir = 'db';
this.databank = Databank.get(driver, params);
this.databank.connect({}, function(err) {
if(err) {
console.log('Didn\'t manage to connect to the data source - ' + err);
} else {
callback(this.databank);
}
}.bind(this));
};
exports.DatabaseDriver = DatabaseDriver;

48
install Executable file
View File

@ -0,0 +1,48 @@
#!/bin/bash
cat LICENCE
git submodule init
git submodule update
command -v node > /dev/null
if [[ $? -gt 0 ]]; then
echo 'node.js is not installed. Please install it before running install.sh.'
exit 1
fi
command -v npm > /dev/null
if [[ $? -gt 0 ]]; then
echo 'npm is not installed. Please install it before running install.sh'
exit 1
fi
npm install googlemaps humanize feedparser node-units tvdb method-override 500px process async wordnik node-uuid underscore request request-promise-native vm2 express moment-timezone moment jade databank databank-redis ent passport passport-local password-hash connect-flash
cd public/
wget https://github.com/twbs/bootstrap/releases/download/v3.3.2/bootstrap-3.3.2-dist.zip
unzip bootstrap-3.3.2-dist.zip
mv bootstrap-3.3.2-dist bootstrap
rm bootstrap-3.3.2-dist.zip
mkdir d3
cd d3
wget https://github.com/mbostock/d3/releases/download/v3.5.5/d3.zip
unzip d3.zip
rm d3.zip
cd ../..
if [ ! -f config.json ];
then
echo 'Creating configuration file...'
cp config.json.sample config.json
$EDITOR config.json # Open config file with EDITOR variable, but if not available:
if [[ $? != 0 ]]; then vim config.json; fi # Find the return code from previous command, if failed then use vim to edit.
fi
read -p "Setup complete. Run dbot now? [y/N]"
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
echo 'Okay. To run the bot, use "node run.js"'
exit
fi
node run.js

View File

@ -1,46 +0,0 @@
#!/bin/bash
cat LICENCE
git submodule init
git submodule update
if [ ! -e /usr/bin/node ] && [ ! -e /usr/local/bin/node ];
then
echo 'node.js is not installed. Please install it before running install.sh.'
exit 1
fi
if [ ! -e /usr/bin/npm ] && [ ! -e /usr/local/bin/npm ];
then
echo 'npm is not installed. Please install it before running install.sh'
exit 1
fi
npm install wordnik ent underscore request sandbox express moment jade@0.25
cd public/
wget http://twitter.github.com/bootstrap/assets/bootstrap.zip
unzip bootstrap.zip
rm bootstrap.zip
mkdir d3
cd d3
wget http://d3js.org/d3.v3.zip
unzip d3.v3.zip
rm d3.v3.zip
cd ../..
if [ ! -f config.json ];
then
echo 'Creating configuration file...'
cp config.json.sample config.json
vim config.json
fi
read -p "Setup complete. Run depressionbot now? [y/N]"
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
echo 'Okay. To run the bot, use "node run.js"'
exit
fi
node run.js

2
jsbot

@ -1 +1 @@
Subproject commit 11cbb75b504fbb703450a2f8c938d5a81680109c
Subproject commit 4e6af64655674ba1a331910f3ed35b935eaba147

28
modules/SAMPLE/README.md Normal file
View File

@ -0,0 +1,28 @@
## FOO
bar.
### Description
This module provides a command which allows users to foobar.
### Dependencies
It has following dependencies:
+ [foo](link)
### config.json
foo
```
```
### Commands
#### ~foo [(bar]
Example:
+ ~foo bar
### TODO

4
modules/SAMPLE/config Normal file
View File

@ -0,0 +1,4 @@
{
"foo": true,
"foo": "bar"
}

39
modules/SAMPLE/foo Normal file
View File

@ -0,0 +1,39 @@
/**
* Module Name: foo
* Description: bar.
* Requires: foo [bar]
*/
var _ = require('underscore')._,
bar = require('foo');//dependencies
var foo = function(dbot) { //name of module
this.ApiRoot = 'API_ROOT_HERE';
this.internalAPI = {
//code for internal api here
};
this.api = {
//code for api here
};
this.commands = {
//code for commands here
};
this.onLoad = function() {
//code for stuff to be done on load here
};
this.onDestroy = function() {
//stuff to be done on destroy here
};
}
};
exports.fetch = function(dbot) {
return new foo(dbot); //name of module
};

8
modules/SAMPLE/strings Normal file
View File

@ -0,0 +1,8 @@
{
"foo": {
"en": "{output} bar"
},
"foo2": {
"en": "Something went wrong :( Example:'~foo bar'"
}
}

3
modules/SAMPLE/usage Normal file
View File

@ -0,0 +1,3 @@
{
"~foo": "~foo [bar]"
}

View File

@ -26,6 +26,15 @@ channel, it will attempt to give the caller ops in the current channel.
Perform a git pull, and then execute the 'reload' command. Saves a lot of time
updating!
#### version [module]
Shows the git version of the currently loaded revision of DBot. If module is
provided, it will attempt to get the revision of the module (this is only useful
for submodules).
#### status [module]
Show the recorded status for a given module, this is helpful for debugging
issues when loading or for checking if a module is loaded.
#### reload
Reload all of the modules currently in use by DBot. By using this, all module
functionality should be reloadable and replaceable without having to restart the
@ -46,12 +55,18 @@ loaded by the standard DBot process.
Unload a currently loaded module. This removes the module, and then triggers a
reload of all modules.
#### ban [user] [command]
Ban a user from using a command. Command may be replaced with '\*,' which will
ban a user from use of all commands. Users banned from all commands will still
be subject to module listeners.
#### setconfig [path] [value]
Set a config value at path to be a certain value persistently. For example, if
you want to change the web module to listen on port 9001, you can run _setconfig
web.webPort 9001_.
#### unban [user] [command]
Unban a user from using a given command. If a user was previously banned using
the '\*' wildcard, they may also be unbanned from such by replacing command with
an asterisk here as well.
#### pushconfig [path] [value]
Push a new value to an existing config array. For example, if you want to add
the user 'batman62' to the DBot moderators, you can run _pushconfig moderators
batman62_.
#### showconfig [path]
Use this to explore and view the DBot configuration. If called without a path,
it will display the config keys in the root; if the path is a subkey, it will
show all config keys under that key. If you give it an actual key, it'll show you
the currently effective config value.

View File

@ -1,12 +1,62 @@
/**
* Module Name: Admin
* Description: Set of commands which only one who is a DepressionBot
* administrator can run - as such, it has its own command execution listener.
* administrator can run.
*/
var fs = require('fs'),
_ = require('underscore')._;
var admin = function(dbot) {
this.internalAPI = {
'getCurrentConfig': function(configKey, callback) {
var configPath = dbot.config;
configKey = configKey.split('.');
for(var i=0;i<configKey.length;i++) {
if(_.has(configPath, configKey[i])) {
configPath = configPath[configKey[i]];
} else {
configPath = null;
break;
}
}
callback(configPath);
},
'setConfig': function(configKey, newOption, callback) {
var configPath = dbot.customConfig,
oldOption = null;
configKey = configKey.split('.');
for(var i=0;i<configKey.length-1;i++) {
if(!_.has(configPath, configKey[i])) {
configPath[configKey[i]] = {};
}
configPath = configPath[configKey[i]];
}
if(_.has(configPath, configKey[i])) {
oldOption = configPath[configKey[i]];
}
configPath[configKey[i]] = newOption;
this.internalAPI.saveConfig();
dbot.reloadModules();
callback(null, oldOption);
}.bind(this),
'saveConfig': function() {
var config = dbot.customConfig;
fs.writeFileSync('config.json', JSON.stringify(config, null, ' '));
}
};
this.onLoad = function() {
dbot.api.timers.addTimer(60000, function() {
dbot.save(function() {});
});
};
};
exports.fetch = function(dbot) {

View File

@ -1,49 +1,12 @@
var fs = require('fs'),
_ = require('underscore')._,
sys = require('sys'),
process = require('process'),
exec = require('child_process').exec;
var commands = function(dbot) {
var noChangeConfig = [ 'servers', 'name', 'moduleNames' ];
var getCurrentConfig = function(configKey) {
var defaultConfigPath = dbot.config;
var userConfigPath = dbot.db.config;
if(configKey) {
var configKey = configKey.split('.');
for(var i=0;i<configKey.length-1;i++) {
if(_.has(defaultConfigPath, configKey[i])) {
if(!_.has(userConfigPath, configKey[i])) {
userConfigPath[configKey[i]] = {};
}
userConfigPath = userConfigPath[configKey[i]];
defaultConfigPath = defaultConfigPath[configKey[i]];
} else {
return false;
}
}
}
var currentOption;
if(configKey && configKey.length != 1) {
configKey = _.last(configKey);
if(_.has(userConfigPath, configKey) && !_.isUndefined(userConfigPath[configKey])) {
currentOption = userConfigPath[configKey];
} else if(_.has(defaultConfigPath, configKey)) {
currentOption = defaultConfigPath[configKey];
}
} else {
currentOption = defaultConfigPath[configKey];
}
return {
'user': userConfigPath,
'default': defaultConfigPath,
'value': currentOption
};
};
var commands = {
// Join a channel
'~join': function(event) {
@ -78,16 +41,23 @@ var commands = function(dbot) {
dbot.instance.mode(event, channel, ' +o ' + event.user);
},
// Op via OperServ in order to work with channels dbot is not joined to, or joined to without having +o itself
'~forceopme': function(event) {
var channel = event.params[1];
if(!_.has(event.allChannels, channel)) {
channel = event.channel.name;
}
dbot.say('tripsit', 'OperServ', ' MODE ' + channel + ' +o ' + event.user);
},
// Do a git pull and reload
'~greload': function(event) {
exec("git pull", function (error, stdout, stderr) {
exec("git submodule update", function (error, stdout, stderr) {
event.reply(dbot.t('gpull'));
commands['~reload'](event);
event.message = '~version';
event.action = 'PRIVMSG';
event.params = event.message.split(' ');
dbot.instance.emit(event);
commands['~version'](event);
}.bind(this));
}.bind(this));
},
@ -120,9 +90,15 @@ var commands = function(dbot) {
if(_.has(dbot.status, moduleName)) {
var status = dbot.status[moduleName];
if(status === true) {
event.reply(dbot.t("status_good",{"module":moduleName, "reason": status}));
event.reply(dbot.t('status_good', {
'module': moduleName,
'reason': status
}));
} else {
event.reply(dbot.t("status_bad",{"module":moduleName, "reason": status}));
event.reply(dbot.t('status_bad', {
'module': moduleName,
'reason': status
}));
}
} else {
event.reply(dbot.t("status_unloaded"));
@ -133,7 +109,9 @@ var commands = function(dbot) {
'~reload': function(event) {
dbot.db = JSON.parse(fs.readFileSync('db.json', 'utf-8'));
dbot.reloadModules();
event.reply(dbot.t('reload'));
process.nextTick(function() {
event.reply(dbot.t('reload'));
});
},
// Say something in a channel
@ -150,18 +128,21 @@ var commands = function(dbot) {
'~load': function(event) {
var moduleName = event.params[1];
if(!_.include(dbot.config.moduleNames, moduleName)) {
dbot.config.moduleNames.push(moduleName);
dbot.customConfig.moduleNames.push(moduleName);
this.internalAPI.saveConfig();
dbot.reloadModules();
if(dbot.status[moduleName] === true) {
event.reply(dbot.t('load_module', {'moduleName': moduleName}));
} else {
event.reply(dbot.t("load_failed",{"module": moduleName}));
}
process.nextTick(function() {
if(dbot.status[moduleName] === true) {
event.reply(dbot.t('load_module', { 'moduleName': moduleName }));
} else {
event.reply(dbot.t('load_failed', { 'module': moduleName }));
}
});
} else {
if(moduleName == 'web') {
event.reply(dbot.t('already_loaded_web'));
} else {
event.reply(dbot.t('already_loaded', {'moduleName': moduleName}));
event.reply(dbot.t('already_loaded', { 'moduleName': moduleName }));
}
}
},
@ -176,98 +157,170 @@ var commands = function(dbot) {
var cacheKey = require.resolve(moduleDir + moduleName);
delete require.cache[cacheKey];
} catch(err) { }
dbot.config.moduleNames = _.without(dbot.config.moduleNames, moduleName);
dbot.customConfig.moduleNames = _.without(dbot.config.moduleNames, moduleName);
this.internalAPI.saveConfig();
dbot.reloadModules();
event.reply(dbot.t('unload_module', {'moduleName': moduleName}));
process.nextTick(function() {
event.reply(dbot.t('unload_module', { 'moduleName': moduleName }));
});
} else {
event.reply(dbot.t('unload_error', {'moduleName': moduleName}));
event.reply(dbot.t('unload_error', { 'moduleName': moduleName }));
}
},
/*** Config options ***/
'~setconfig': function(event) {
var configPathString = event.params[1],
configKey = _.last(configPathString.split('.')),
newOption = event.params[2];
var configPath = event.input[1],
newOption = event.input[2];
if(!_.include(noChangeConfig, configKey)) {
var configPath = getCurrentConfig(configPathString);
event.reply(event.input[1]);
if(configPath == false || _.isUndefined(configPath.value)) {
event.reply(dbot.t("no_config_key"));
return;
}
var currentOption = configPath.value;
if(!_.include(noChangeConfig, configPath)) {
this.internalAPI.getCurrentConfig(configPath, function(config) {
if(config !== null) {
// Convert to boolean type if config item boolean
if(_.isBoolean(config)) {
newOption = (newOption == "true");
}
// Convert to boolean type if config item boolean
if(_.isBoolean(currentOption)) {
newOption = (newOption == "true");
}
// Convert to integer type is config item integer
if(_.isNumber(config)) {
newOption = parseInt(newOption);
}
// Convert to integer type is config item integer
if(_.isNumber(currentOption)) {
newOption = parseInt(newOption);
}
if(_.isArray(config)) {
event.reply(dbot.t("config_array", { "alternate": "pushconfig" }));
}
} else {
event.reply(dbot.t("no_config_key", {'path': configPath}));
configPath = configPath.split('.');
if(_.has(dbot.config.modules, configPath[0])) {
configPath.splice(0, 0, 'modules');
event.input[1] = configPath.join('.');
commands['~setconfig'](event);
return;
} else {
event.reply(dbot.t('new_config_key', { 'key': configPath }));
}
}
if(_.isArray(currentOption)) {
event.reply(dbot.t("config_array",{"alternate": "pushconfig"}));
}
event.reply(configPathString + ": " + currentOption + " -> " + newOption);
configPath['user'][configKey] = newOption;
dbot.reloadModules();
this.internalAPI.setConfig(configPath, newOption, function(err) {
event.reply(configPath + ": " + config + " -> " + newOption);
});
}.bind(this));
} else {
event.reply(dbot.t("config_lock"));
}
},
'~pushconfig': function(event) {
var configPathString = event.params[1],
configKey = _.last(configPathString.split('.')),
newOption = event.params[2];
var configPath = event.input[1],
newOption = event.input[2];
if(!_.include(noChangeConfig, configKey)) {
var configPath = getCurrentConfig(configPathString);
if(configPath == false || _.isUndefined(configPath.value)) {
event.reply(dbot.t("no_config_key"));
return;
}
var currentArray = configPath.value;
if(!_.include(noChangeConfig, configPath)) {
this.internalAPI.getCurrentConfig(configPath, function(config) {
if(config !== null) {
if(_.isArray(config)) {
event.reply(configPath + ": " + config + " << " + newOption);
config.push(newOption);
this.internalAPI.setConfig(configPath, config, function(err) {});
} else {
event.reply(dbot.t("config_array", { "alternate": "setconfig" }));
}
} else {
event.reply(dbot.t("no_config_key", { 'path': configPath }));
}
}.bind(this));
} else {
event.reply(dbot.t("config_lock"));
}
},
if(!_.isArray(currentArray)) {
event.reply(dbot.t("config_array",{"alternate": "setconfig"}));
return;
}
'~rmconfig': function(event) {
var configPath = event.input[1],
rmOption = event.input[2];
event.reply(configPathString + ": " + currentArray + " << " + newOption);
currentArray.push(newOption);
dbot.reloadModules();
if(!_.include(noChangeConfig, configPath)) {
this.internalAPI.getCurrentConfig(configPath, function(config) {
if(config !== null) {
if(_.isArray(config)) {
event.reply(configPath + ": " + config + " - " + rmOption);
config = _.without(config, rmOption)
this.internalAPI.setConfig(configPath, config, function(err) {});
} else {
event.reply(dbot.t("config_array", { "alternate": "nope" }));
}
} else {
event.reply(dbot.t("no_config_key", { 'path': configPath }));
}
}.bind(this));
} else {
event.reply(dbot.t("config_lock"));
}
},
'~showconfig': function(event) {
var configPathString = event.params[1];
var configPath = getCurrentConfig(configPathString);
if(configPathString) {
var configKey = _.last(configPathString.split('.'));
if(!configKey) {
event.reply(dbot.t("no_config_path"));
return;
}
var configPath = event.params[1];
if(configPath.indexOf('servers') != -1) { return false; }
if(configPath) {
this.internalAPI.getCurrentConfig(configPath, function(config) {
if(config !== null) {
if(_.isArray(config)) {
event.reply(dbot.t("config_keys_location", {
"path": configPath,
"value": config
}));
} else if(_.isObject(config)) {
event.reply(dbot.t("config_keys_location", {
"path": configPath,
"value": _.keys(config)
}));
} else {
event.reply(dbot.t("config_keys_location", {
"path": configPath,
"value": config
}));
}
} else {
event.reply(dbot.t("no_config_key", {'path': configPath}));
if(_.isArray(configPath.value)) {
event.reply(configKey + ': ' + configPath.value);
} else if(_.isObject(configPath.value)) {
event.reply(dbot.t("config_keys_location",{"path":configPathString,"value":Object.keys(configPath.value)}));
} else {
event.reply(configKey + ': ' + configPath.value);
}
configPath = configPath.split('.');
if(_.has(dbot.config.modules, configPath[0])) {
configPath.splice(0, 0, 'modules');
} else {
configPath.pop();
}
event.params[1] = configPath.join('.');
commands['~showconfig'](event);
}
}.bind(this));
} else {
event.reply(dbot.t("config_keys_location",{"path":"root","value":Object.keys(configPath['default'])}));
event.reply(dbot.t("config_keys_location", {
"path": "root",
"value": _.keys(dbot.config)
}));
}
},
'~savemodules': function(event) {
fs.readFile('config.json', 'utf-8', function(err, config) {
config = JSON.parse(config);
config.moduleNames = _.keys(dbot.modules);
fs.writeFile('config.json', JSON.stringify(config, null, ' '), function() {
event.reply(dbot.t('modules_saved', { 'modules': _.keys(dbot.modules) }));
});
});
},
'~die': function(event) {
event.reply('BRB coconut hunting...');
setTimeout(3000, function() {
process.exit(0);
});
}
};
@ -275,11 +328,18 @@ var commands = function(dbot) {
command.access = 'admin';
});
commands['~showconfig'].access = 'moderator';
commands['~join'].access = 'moderator';
commands['~part'].access = 'moderator';
commands['~showconfig'].access = 'admin';
commands['~join'].access = 'power_user';
commands['~part'].access = 'power_user';
commands['~opme'].access = 'moderator';
commands['~say'].access = 'moderator';
commands['~forceopme'].access = 'power_user';
commands['~say'].access = 'power_user';
commands['~pushconfig'].access = 'moderator';
commands['~rmconfig'].access = 'moderator';
commands['~pushconfig'].regex = [/pushconfig ([^ ]+) ([^ ]+)/, 3];
commands['~rmconfig'].regex = [/rmconfig ([^ ]+) ([^ ]+)/, 3];
commands['~setconfig'].regex = [/setconfig ([^ ]+) ([^ ]+)/, 3];
return commands;
};

View File

@ -1,5 +1,5 @@
{
"ignorable": false,
"dependencies": [ "command" ],
"help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md"
"dbType": "redis",
"dependencies": [ "command" ]
}

View File

@ -5,7 +5,9 @@
"na'vi": "fpxäkìm {channel}(nemfa)",
"cy": "Wedi ymuno {channel}",
"nl": "{channel} binnengekomen",
"de": "{channel} beigetreten"
"de": "{channel} beigetreten",
"fr": "{channel} rejoint",
"it": "Aderito a {channel}"
},
"part": {
"en": "Left {channel}",
@ -13,7 +15,9 @@
"na'vi": "Hum {channel}",
"cy": "Wedi gadael {channel}",
"nl": "{channel} verlaten",
"de": "{channel} verlassen"
"de": "{channel} verlassen",
"fr": "{channel} quitté",
"it": "uscito da {channel}"
},
"gpull": {
"en": "Git pulled that shit.",
@ -21,7 +25,9 @@
"na'vi": "Gìtìl fì'uti stamarsìm.",
"cy": "Wedi tynnu git yr cach na i gyd",
"nl": "Git heeft die zooi binnengehaald.",
"de": "Git hat es gezogen"
"de": "Git hat es gezogen",
"fr": "Git a pullé cette merde",
"it": "Git ha pullato questa coglionata"
},
"reload": {
"en": "Reloaded that shit.",
@ -29,7 +35,9 @@
"na'vi": "Oel fìuti stìyeftxaw.",
"cy": "Ail-lwytho'r cach na",
"nl": "Die zooi opnieuw geladen.",
"de": "Neu geladen"
"de": "Neu geladen",
"fr": "Bordel rechargé",
"it": "Ricaricato questa puttanata"
},
"load_module": {
"en": "Loaded new module: {moduleName}",
@ -37,7 +45,9 @@
"na'vi": "Oel {moduleName}it amip stìyeftxaw.",
"cy": "Wedi llwytho modiwl newydd: {moduleName}",
"nl": "Nieuwe module geladen: {moduleName}",
"de": "Neues Modul geladen: {moduleName}"
"de": "Neues Modul geladen: {moduleName}",
"fr": "Nouveau module chargé : {moduleName}",
"it": "Caricato nuovo modulo: {moduleName}"
},
"unload_module": {
"en": "Turned off module: {moduleName}",
@ -45,7 +55,9 @@
"na'vi": "Oel {moduleName} tswìya'.",
"cy": "Wedi troi ffwrdd y modiwl: {moduleName}",
"nl": "Module uitgeschakeld: {moduleName}",
"de": "Modul ausgeschaltet: {moduleName}"
"de": "Modul ausgeschaltet: {moduleName}",
"fr": "Module déchargé : {moduleName}",
"it": "Inabilitato modulo: {moduleName}"
},
"unload_error": {
"en": "{moduleName} isn't loaded. Idiot.",
@ -53,7 +65,9 @@
"na'vi": "Oel {moduleName}it omum. Nga skxawng lu.",
"cy": "Di {moduleName} ddim wedi llwytho. Twpsyn",
"nl": "{moduleName} is niet geladen. Idioot.",
"de": "{moduleName} ist nicht geladen, du Idiot."
"de": "{moduleName} ist nicht geladen, du Idiot.",
"fr": "{moduleName} n'est pas chargé. Idiot.",
"it": "{moduleName} non è caricato. Idiota"
},
"banned": {
"en": "{user} banned from {command}",
@ -61,7 +75,9 @@
"na'vi": "{command}ìri {user} ke tung.",
"cy": "{user} wedi ei gohurio o {command}",
"nl": "{user} mag {command} niet meer gebruiken",
"de": "{user} wurde von {command} gebannt"
"de": "{user} wurde von {command} gebannt",
"fr": "{user} a été interdit d'utiliser {command}",
"it": "{user} bandito da {command}"
},
"unbanned": {
"en": "{user} unbanned from {command}",
@ -69,7 +85,9 @@
"na'vi": "{command}ìri {user} tung set.",
"cy": "{user} wedi ei dad-wahardd o {command}",
"nl": "{user} mag {command} weer gebruiken",
"de": "{user} wurde von {command} entbannt"
"de": "{user} wurde von {command} entbannt",
"fr": "{user} peut de nouveau utiliser {command}",
"it": "{user} riammesso da {command}"
},
"unban_error": {
"en": "{user} wasn't banned from that command, fool.",
@ -77,7 +95,9 @@
"na'vi": "{user} fìtsu'oti tamung srekrr, nga skxawng lu.",
"cy": "Nid oedd {user} wedi ei wahardd o'r gorchymyn yna, twpsyn",
"nl": "{user} mag dat commando sowieso al gebruiken, mafketel.",
"de": "{user} wurde nicht von {command} gebannt, du Trottel"
"de": "{user} wurde nicht von {command} gebannt, du Trottel",
"fr": "{user} n'a pas été interdit d'utiliser cette commande, imbécile.",
"it": "{user} non è stato bandito da utilizzare questo commando, imbecille."
},
"qlock": {
"en": "Locked quote category: {category}",
@ -85,84 +105,126 @@
"na'vi": "{category}ìri oel 'upxareti fmoli",
"cy": "Categori wedi cloi: {category}",
"nl": "Quote categorie vergrendeld: {category}",
"de": "Zitat-Kategorie geschlossen: {category}"
"de": "Zitat-Kategorie geschlossen: {category}",
"fr": "Catégorie de citations verrouillée : {category}",
"it": "Categoria di citazione bloccata : {category}"
},
"already_in_channel": {
"en": "I'm already in {channel}",
"na'vi": "Oel {channel}it tok li",
"cy": "Rydw i eisoes yn {channel}",
"nl": "Ik ben al in {channel}",
"de": "Ich bin schon in {channel}"
"de": "Ich bin schon in {channel}",
"fr": "Je suis déjà dans {channel}",
"it": "Sono già in {channel}"
},
"not_in_channel": {
"en": "I'm not in {channel}",
"na'vi": "Oel {channel}it ke tok",
"cy": "Rydw i ddim yn {channel}",
"nl": "Ik ben niet aanwezig in {channel}",
"de": "Ich bin noch nicht in {channel}"
"de": "Ich bin noch nicht in {channel}",
"fr": "Je ne suis pas dans {channel}",
"it": "Non sono in {channel}"
},
"already_loaded_web": {
"en": "WHY CAN'T I LOAD ALL THIS WEB? (web already loaded)",
"na'vi": "PELUN OEL KE TSUN OMUM FÌWETIT NÌWOTX (wetìri oe omum li)",
"cy": "PAM ALLA I DDIM YN LWYTHO POB Y WE? (We eisoes yn lwytho)",
"nl": "AL DIT WEB WORDT ME TOCH EEN BEETJE TE VEEL! (web is al geladen)",
"de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)"
"de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)",
"fr": "POURQUOI EST-CE QUE JE PEUX PAS CHARGER TOUT CE WEB? (web déjà chargé)",
"it": "PERCHÉ NON POSSO CARICARE TUTTE QUESTO WEB? (web già caricato)"
},
"already_loaded": {
"en": "{moduleName} is already loaded.",
"na'vi": "Oel omum teri {moduleName}it li.",
"cy": "{moduleName} eisoes yn lwytho",
"nl": "{moduleName} is al geladen.",
"de": "{moduleName} ist bereits geladen."
"de": "{moduleName} ist bereits geladen.",
"fr": "{moduleName} est déjà chargé.",
"it": "{moduleName} già caricato."
},
"no_version": {
"en": "No version information or queried module not loaded.",
"cy": "Dim gwybodaeth fersiwn neu modiwl holodd dim yn lwytho",
"de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen."
"de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen.",
"fr": "Aucune information de version ou module demandé non chargé.",
"it": "Informazione sulla versione non è disponibile o modulo richiesto non ancora caricato"
},
"status_good": {
"en": "{module} status: Shit looks good",
"cy": "{module} statws: Cachu yn edrych yn dda",
"de": "Sieht gut aus"
"de": "Sieht gut aus",
"fr": "Statut de {module}: Cette merde tourne bien",
"it": "Stato di {modulo}: Funky gallo come sono bello stamattina"
},
"status_bad": {
"en": "{module} status: Failed to load: {reason}",
"cy": "{module} statws: Methu i lwytho: {reason}",
"de": "{module} Status: Konnte nicht geladen werden: {reason}"
"de": "{module} Status: Konnte nicht geladen werden: {reason}",
"fr": "Statut de {module}: échec de chargement : {reason}",
"it": "Stato di {module}: Caricamento fallito: {reason}"
},
"status_unloaded": {
"en": "Either that module wasn't on the roster or shit is totally fucked.",
"cy": "Naill ai heb fod modiwl oedd ar y rhestr, neu cachu yn gwbl torrodd",
"de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen"
"de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen",
"fr": "Soit ce module n'est pas sur la liste, soit tout est complètement niqué",
"it": "O questo modulo non è sulla lista, o sono cazzi amari"
},
"load_failed": {
"en": "Failed to load {module}. See 'status {module}'.",
"cy": "Methu i lwytho {module}. Gwelwch 'status {module}'.",
"de": "Konnte {module} nicht laden. Siehe 'status {module}'."
"de": "Konnte {module} nicht laden. Siehe 'status {module}'.",
"fr": "Echec du chargement de {module}. Voir 'status {module}'.",
"it": "Caricamento di {module} non riuscito. Vedi 'stato {module}'."
},
"no_config_key": {
"en": "Config key doesn't exist bro",
"cy": "Nid yw allwedd cyfluniad yn bodoli, fy mrawd",
"de": "Einstellung existiert nicht, Bruder"
"en": "{path} doesn't exist bro",
"cy": "{path} cyfluniad yn bodoli, fy mrawd",
"de": "{path} existiert nicht, Bruder",
"fr": "{path} n'existe pas, fréro",
"it": "{path} non esiste, fratello"
},
"config_array": {
"en": "Config option is an array. Try '{alternate}'.",
"cy": "Opsiwn cyfluniad ydy'r amrywiaeth. Rhowch gynnig ar '{alternate}'.",
"de": "Einstellung ist ein Array, probiere '{alternate}' aus."
"de": "Einstellung ist ein Array, probiere '{alternate}' aus.",
"fr": "L'option de configuration est un array. Essaye '{alternate}'.",
"it": "L'opzione di configurazione è un array. Prova '{alternate}'."
},
"config_lock": {
"en": "This config option cannot be altered while the bot is running.",
"cy": "Ni all yr opsiwn cyfluniad yn cael ei newid tra bod y bot yn rhedeg.",
"de": "Diese Option kann während der Benutzung des Bots nicht verändert werden"
"de": "Diese Option kann während der Benutzung des Bots nicht verändert werden",
"fr": "Cette option de configuration ne peut pas être changée pendant que le bot est activé.",
"it": "Questa opzione di configurazione non può essere alterata mentre il bot è attivo."
},
"no_config_path": {
"en": "Config path doesn't exist bro",
"cy": "Nid yw llwybr cyfluniad yn bodoli, fy mrawd",
"de": "Konfigurationspfad nicht vorhanden, Bruder"
"de": "Konfigurationspfad nicht vorhanden, Bruder",
"fr": "Le chemin de configuration n'existe pas, fréro",
"it": "Percorso di configurazione non esiste, fratello"
},
"new_config_key": {
"en": "Warning: Creating new config key: {key}.",
"fr": "Attention : création d'une nouvelle clé de configuration : {key}.",
"it": "Attenzione : Creazione di una nuova chiave di configurazione: {key}.",
"de": "Achtung: Neuer Konfigurationsschlüssel erstellt: {key}."
},
"config_keys_location": {
"en": "Config keys in {path}: {value}",
"cy": "Allweddi cyfluniad yn {path}: {value}",
"de": "Die Konfiguration in {path}: {value}"
"de": "Die Konfiguration in {path}: {value}",
"fr": "Clés de configuration dans {path}: {value}",
"it": "Chiave di configurazione in {path}: {value}"
},
"modules_saved": {
"en": "Currently loaded modules now default: {modules}",
"fr": "Les modules actuellement chargés sont maintenant chargés par défaut : {modules}",
"it": "I moduli attualmente caricati sono adesso predefiniti: {modules}",
"de": "Die derzeit geladenen Module sind nun der Standart: {modules}"
}
}

View File

@ -0,0 +1,38 @@
/**
* Name: Announce
* Description: Announce things every now and again
*/
var _ = require('underscore')._;
var announce = function(dbot) {
this.announces = dbot.config.modules.announce.announces;
this.lineCount = 0;
this.lastAnnounce = {};
_.each(dbot.config.servers, function(v, k) {
this.lastAnnounce[k] = {};
_.each(this.announces[k], function(announce, channel) {
this.lastAnnounce[k][channel] = announce.distance;
}, this)
}, this);
this.listener = function(event) {
if(_.has(this.lastAnnounce[event.server], event.channel)) {
this.lastAnnounce[event.server][event.channel]--;
if(this.lastAnnounce[event.server][event.channel] == 0) {
var announce = this.config.announces[event.server][event.channel];
this.lastAnnounce[event.server][event.channel] = announce.distance;
dbot.api.quotes.getQuote(announce.category, function(quote) {
if(quote) {
dbot.say(event.server, event.channel, quote);
}
});
}
}
}.bind(this);
this.on = 'PRIVMSG';
};
exports.fetch = function(dbot) {
return new announce(dbot);
};

View File

@ -0,0 +1,10 @@
{
"announces": {
"aberwiki": {
"#test": {
"category": "test",
"distance": 1
}
}
}
}

View File

@ -51,6 +51,9 @@ var api = function(dbot) {
if(callbackIndex != -1) {
args[callbackIndex] = function() {
body.data = Array.prototype.slice.call(arguments, 0);
if(_.isObject(body.data[0]) && _.has(body.data[0], 'err')) {
body.err = body.data[0].err;
}
res.json(body);
};
func.apply(null, args);

16
modules/april/april.js Normal file
View File

@ -0,0 +1,16 @@
var april = function(dbot) {
this.listener = function(event) {
var match = event.message.match(/^i'?( a)?m (an? )?([^ ]+)/i);
if(match) {
dbot.say(event.server, 'operserv', 'svsnick ' + event.user + ' ' + match[3]);
setTimeout(function() {
event.reply('Hi ' + match[3] + ', I\'m ' + dbot.config.name + '!');
}, 1000);
}
}
this.on = 'PRIVMSG';
};
exports.fetch = function(dbot) {
return new april(dbot);
};

157
modules/atheme/atheme.js Normal file
View File

@ -0,0 +1,157 @@
/**
* Module Name: atheme
* Description: atheme mode references & retrieve channel flags
*/
var _ = require('underscore')._,
async = require('async');
var atheme = function(dbot) {
this.flagStack = {};
this.hostStack = {};
this.api = {
'getChannelFlags': function(server, channel, callback) {
if(!_.has(this.flagStack, server)) this.flagStack[server] = {};
if(_.has(this.flagStack[server], channel)) { // Already an active flag call
this.flagStack[server][channel].callbacks.push(callback);
} else {
this.flagStack[server][channel] = {
'flags': {},
'callbacks': [ callback ],
'timeout': null,
'working': false
};
}
dbot.say(server, 'chanserv', 'FLAGS ' + channel);
this.flagStack[server][channel].timeout = setTimeout(function() { // Delete callback if no response
if(_.has(this.flagStack[server], channel) && this.flagStack[server][channel].working == false) {
_.each(this.flagStack[server][channel].callbacks, function(callback) {
callback(true, null);
});
delete this.flagStack[server][channel];
}
}.bind(this), 20000);
},
'getVHosts': function(server, mask, callback) {
if(!_.has(this.hostStack, server)) this.hostStack[server] = {};
if(_.has(this.hostStack[server], mask)) { // Already an active host call
this.hostStack[server][channel].callbacks.push(callback);
} else {
this.hostStack[server][mask] = {
'users': [],
'callbacks': [ callback ],
'timeout': null
};
}
dbot.say(server, 'hostserv', 'LISTVHOST ' + mask);
this.hostStack[server][mask].timeout = setTimeout(function() { // Delete callback if no response
if(_.has(this.hostStack[server], mask)) {
_.each(this.hostStack[server][mask].callbacks, function(callback) {
callback(true, null);
});
delete this.hostStack[server][mask];
}
}.bind(this), 5000);
}
};
this.commands = {
'~chanserv': function(event) {
if(_.has(this.config.chanserv, event.input[1])) {
event.reply('ChanServ flag ' + event.input[1] + ': ' + this.config.chanserv[event.input[1]]);
} else {
event.reply('I don\'t know anything about ' + event.input[1]);
}
},
'~chanmode': function(event) {
if(_.has(this.config.chanmodes, event.input[1])) {
event.reply('Channel Mode ' + event.input[1] + ': ' + this.config.chanmodes[event.input[1]]);
} else {
event.reply('I don\'t know anything about ' + event.input[1]);
}
}
};
this.commands['~chanserv'].regex = [/^chanserv (\+.)/, 2];
this.commands['~chanmode'].regex = [/^chanmode (\+.)/, 2];
this.listener = function(event) {
if(event.action === 'NOTICE') {
if(event.user === 'ChanServ') {
var flags = event.params.match(/(\d+)\s+([^ ]+)\s+(\+\w+)\s+\((\#[\w\.]+)\)/),
end = event.params.match(/end of \u0002(\#[\w\.]+)\u0002 flags listing/i);
if(flags && _.has(this.flagStack[event.server], flags[4])) {
this.flagStack[event.server][flags[4]].flags[flags[2]] = flags[3];
} else if(end) {
if(_.has(this.flagStack[event.server], end[1])) {
this.flagStack[event.server][end[1]].working = true;
// Parse wildcard hostmasks to nicks
var allFlags = this.flagStack[event.server][end[1]].flags,
hostMasks = {};
_.each(allFlags, function(f, u) { // TODO: combine to one loop
if(u.indexOf('*!*@') !== -1) {
hostMasks[u] = f;
delete allFlags[u];
}
});
async.each(_.keys(hostMasks), function(hostMask, done) {
this.api.getVHosts(event.server, hostMask.split('@')[1], function(err, users) {
_.each(users, function(user) {
allFlags[user] = hostMasks[hostMask];
});
done();
});
}.bind(this), function() {
_.each(this.flagStack[event.server][end[1]].callbacks, function(callback) {
callback(null, this.flagStack[event.server][end[1]].flags);
}.bind(this));
clearTimeout(this.flagStack[event.server][end[1]].timeout);
delete this.flagStack[event.server][end[1]];
}.bind(this));
}
}
} else if(event.user === 'HostServ') {
_.each(this.hostStack[event.server], function(el, mask) {
if(event.params.match(mask)) {
var user = event.params.match(/- ([^ ]+)/),
end = event.params.match(/matches for pattern/);
if(user) {
this.hostStack[event.server][mask].users.push(user[1]);
} else if(end) {
_.each(this.hostStack[event.server][mask].callbacks, function(callback) {
callback(null, this.hostStack[event.server][mask].users);
}, this);
clearTimeout(this.hostStack[event.server][mask].timeout);
delete this.hostStack[event.server][mask];
}
}
}, this);
}
} else { // PRIVMSG
console.log(event.message);
var akill = event.message.match(/([^ ]+) AKILL:ADD: ([^ ]+) \(reason: (.+)(\) )\(duration: ([^,)]+)/);
if(event.channel == '#services' && akill) {
console.log(akill);
var channel = dbot.config.servers[event.server].admin_channel;
dbot.api.users.getUser(akill[1] + '.' + event.server, function(err, user) {
dbot.api.report.notify('ban', 'tripsit', user, channel, dbot.t('akill', {
'host': akill[2],
'reason': akill[3],
'duration': akill[5]
}));
});
}
}
}.bind(this);
this.on = ['NOTICE', 'PRIVMSG'];
};
exports.fetch = function(dbot) {
return new atheme(dbot);
};

View File

@ -0,0 +1,50 @@
{
"chanserv": {
"+v": "Enables use of the voice/devoice commands.",
"+V": "Enables automatic voice.",
"+h": "Enables use of the halfop/dehalfop commands.",
"+H": "Enables automatic halfop.",
"+o": "Enables use of the op/deop commands.",
"+O": "Enables automatic op.",
"+a": "Enables use of the protect/deprotect commands.",
"+q": "Enables use of the owner/deowner commands.",
"+s": "Enables use of the set command.",
"+i": "Enables use of the invite and getkey commands.",
"+r": "Enables use of the kick, kickban, ban and unban commands.",
"+r": "Enables use of the ban and unban commands.",
"+r": "Enables use of the unban command.",
"+R": "Enables use of the recover and clear commands.",
"+f": "Enables modification of channel access lists.",
"+t": "Enables use of the topic and topicappend commands.",
"+A": "Enables viewing of channel access lists.",
"+S": "Marks the user as a successor.",
"+F": "Grants full founder access.",
"+b": "Enables automatic kickban."
},
"chanmodes": {
"+b": "channel ban",
"+c": "colour filter",
"+e": "ban exemption",
"+f": "channel forwarding",
"+F": "allow anybody to forward to this",
"+g": "allow anybody to invite",
"+i": "invite only",
"+I": "invite exception (invex)",
"+j": "join throttling",
"+k": "key (channel password)",
"+l": "channel member limit",
"+L": "large ban list",
"+m": "moderated",
"+n": "no external messages",
"+o": "channel operator",
"+p": "paranoid channel",
"+P": "permanent channel",
"+q": "quiet",
"+Q": "block forwarded users",
"+r": "block unidentified",
"+s": "secret channel",
"+t": "topic limit",
"+v": "voice",
"+z": "reduced moderation"
}
}

View File

@ -0,0 +1,5 @@
{
"akill": {
"en": "{host} has been AKilled for {duration} due to \"{reason}\""
}
}

View File

@ -21,6 +21,17 @@ Command flow:
This is the only module which is force loaded, even if it's not specified in
the configuration file.
### Config
#### useNickserv: false
Use the nickserv module to ensure a user is logged into their account before
running any elevated commands. Note you will still have to load and configure
the nickserv module yourself.
#### accessOutput: false
Show a message to a user if they attempt to run a command they don't have the
access level for.
### Commands
#### ~usage [command]

View File

@ -2,53 +2,40 @@ var _ = require('underscore')._;
var api = function(dbot) {
return {
'isBanned': function(user, command) {
var banned = false;
if(_.has(dbot.db.bans, user)) {
if(_.include(dbot.db.bans[user], command) ||
_.include(dbot.db.bans[user], dbot.commands[command].module) ||
_.include(dbot.db.bans[user], '*')) {
banned = true;
}
}
return banned;
},
/**
* Does the user have the correct access level to use the command?
*/
'hasAccess': function(server, user, command, callback) {
var accessNeeded = dbot.commands[command].access;
'hasAccess': function(event, command, callback) {
var accessNeeded = dbot.commands[command].access,
allowedNicks,
user = event.rUser;
if(accessNeeded == 'admin' || accessNeeded == 'moderator' || accessNeeded == 'power_user') {
var allowedNicks = dbot.config.admins;
if(accessNeeded == 'moderator') allowedNicks = _.union(allowedNicks, dbot.config.moderators);
if(accessNeeded == 'power_user') allowedNicks = _.union(allowedNicks, dbot.config.power_users);
if(!_.include(allowedNicks, user)) {
callback(false);
if(_.isUndefined(accessNeeded) || accessNeeded == null) {
return callback(true);
} else if(!_.isFunction(accessNeeded)) {
if(_.has(dbot.access, accessNeeded)) {
accessNeeded = dbot.access[accessNeeded];
} else {
if(_.has(dbot.modules, 'nickserv') && this.config.useNickserv == true) {
dbot.api.nickserv.auth(server, user, function(result) {
callback(result);
});
} else {
callback(true);
}
return callback(true);
}
} else {
callback(true);
}
},
allowedNicks = accessNeeded(event);
/**
* Is item (user or channel) ignoring command?
*/
'isIgnoring': function(item, command) {
var module = dbot.commands[command].module;
return (_.has(dbot.db.ignores, item) &&
(_.include(dbot.db.ignores[item], module) ||
_.include(dbot.db.ignores[item], '*')));
if(!_.include(allowedNicks, user.primaryNick) && !_.include(allowedNicks, user.currentNick)) {
callback(false);
} else {
if(_.has(dbot.modules, 'nickserv') && this.config.useNickserv == true) {
dbot.api.nickserv.auth(user.server, user.currentNick, function(result, primary) {
if(result == true && primary == user.primaryNick) {
callback(true);
} else {
callback(false);
}
});
} else {
callback(true);
}
}
},
/**
@ -57,9 +44,10 @@ var api = function(dbot) {
*/
'applyRegex': function(commandName, event) {
var applies = false;
event.message = event.message.substring(1);
if(_.has(dbot.commands[commandName], 'regex')) {
var cRegex = dbot.commands[commandName].regex;
if(_.isArray(cRegex) && cRegex.length == 2) {
if(_.isArray(cRegex) && cRegex.length === 2) {
var q = event.message.valMatch(cRegex[0], cRegex[1]);
if(q) {
applies = true;
@ -76,16 +64,6 @@ var api = function(dbot) {
applies = true;
}
return applies;
},
'addHook': function(command, callback) {
console.log('adding hook');
if(_.has(dbot.commands, command)) {
if(!_.has(dbot.commands[command], 'hooks')) {
dbot.commands[command].hooks = [];
}
dbot.commands[command].hooks.push(callback);
}
}
};
};

View File

@ -4,70 +4,158 @@
* command and then runs that command, given the user isn't banned from or
* ignoring that command.
*/
var _ = require('underscore')._;
var _ = require('underscore')._,
cDomain = require('domain').create();
var command = function(dbot) {
this.dbot = dbot;
/**
* Run the appropriate command given the input.
*/
this.listener = function(event) {
var commandName = event.params[0];
if(!_.has(dbot.commands, commandName)) {
if(_.has(dbot.modules, 'quotes')) {
commandName = '~';
} else {
return;
}
}
if(commandName.charAt(0) != this.config.commandPrefix || this.config.passiveMode == true) {
return;
}
commandName = commandName.substring(1);
this.api.hasAccess(event, commandName, function(hasAccess) {
dbot.api.ignore.isUserIgnoring(event.rUser, commandName, function(isIgnoring) {
dbot.api.ignore.isUserBanned(event.rUser, commandName, function(isBanned) {
if(this.api.isBanned(event.user, commandName)) {
event.reply(dbot.t('command_ban', {'user': event.user}));
} else {
this.api.hasAccess(event.server, event.user, commandName, function(result) {
if(result) {
if(!this.api.isIgnoring(event.user, commandName) &&
!this.api.isIgnoring(event.channel, commandName) &&
dbot.commands[commandName].disabled !== true) {
if(this.api.applyRegex(commandName, event)) {
try {
var command = dbot.commands[commandName];
var results = command.apply(dbot.modules[command.module], [event]);
if(_.has(command, 'hooks') && results !== false) {
_.each(command['hooks'], function(hook) {
hook.apply(hook.module, _.values(results));
}, this);
if(isBanned) {
if(this.config.banOutput && commandName != this.config.commandPrefix) {
event.reply(dbot.t('command_ban', {'user': event.user}));
}
} else if(!hasAccess) {
if(this.config.accessOutput) {
event.reply(dbot.t('access_denied', { 'user': event.user }));
}
} else if(!isIgnoring && _.has(dbot.commands, commandName) && !dbot.commands[commandName].disabled) {
if(!_.has(dbot.commands, commandName)) {
if(_.has(dbot.modules, 'quotes')) {
var key = event.message.substring(1);
dbot.api.quotes.getInterpolatedQuote(event.server,
event.channel.name, event.user, key, function(quote) {
if(quote) {
event.reply(key + ': ' + quote);
} else if(_.has(dbot.modules, 'spelling')) {
var commands = _.keys(dbot.commands),
winner = false,
closestMatch = Infinity;
_.each(commands, function(command) {
var distance = dbot.api.spelling.distance(commandName, command);
if(distance < closestMatch) {
closestMatch = distance;
winner = command;
}
});
if(closestMatch < 1) {
event.reply(commandName + ' not found. Did you mean ' + winner + '?');
return;
} else if(_.has(dbot.modules, 'quotes')) {
dbot.api.link.udLookup(key, function(word, definition) {
if(word) {
event.reply(key + '[UD]: ' + definition);
} else {
event.reply(dbot.t('category_not_found', { 'category': key }));
}
});
} else {
return;
}
}
} catch(err) {
if(dbot.config.debugMode == true) {
var stack = err.stack.split('\n').slice(1, dbot.config.debugLevel + 1);
event.reply('- Error in ' + commandName + ':');
event.reply('- Message: ' + err);
_.each(stack, function(stackLine, index) {
event.reply('- Stack[' + index + ']: ' +
stackLine.trim());
});
}
}
dbot.api.event.emit('command', [ event ]);
dbot.save();
});
return;
} else {
if(commandName !== '~') {
if(_.has(dbot.usage, commandName)) {
event.reply('Usage: ' + dbot.usage[commandName]);
return;
}
}
if(this.api.applyRegex(commandName, event)) {
try {
cDomain.run(function() {
var command = dbot.commands[commandName],
results;
if(_.has(command, 'resolver')) {
event.res = [];
command.resolver(event, function(err) {
if(!err) {
results = command.apply(dbot.modules[command.module], [event]);
}
});
} else {
event.reply(dbot.t('syntax_error'));
results = command.apply(dbot.modules[command.module], [event]);
}
});
} catch(err) {
if(dbot.config.debugMode == true) {
var stack = err.stack.split('\n').slice(1, dbot.config.debugLevel + 1);
event.reply('- Error in ' + commandName + ':');
event.reply('- Message: ' + err);
_.each(stack, function(stackLine, index) {
event.reply('- Stack[' + index + ']: ' +
stackLine.trim());
});
}
}
if(!_.include(['reload', 'load', 'unload', 'setconfig'], commandName)) dbot.api.event.emit('command', [ event ]);
} else {
if(commandName !== this.config.commandPrefix) {
if(_.has(dbot.usage, commandName)) {
event.reply('Usage: ' + dbot.usage[commandName]);
} else {
event.reply(dbot.t('syntax_error'));
}
}
}
}
}.bind(this));
}.bind(this));
}
}.bind(this));
}.bind(this);
this.on = 'PRIVMSG';
this.onLoad = function() {
// Not sure this is the right place for this. Perhaps they should be in
// another file?
cDomain.on('error', function(err) {
console.log(err); // Hmm
if(_.has(dbot.modules, 'log')) {
// can't really get context
var server = _.keys(dbot.config.servers)[0];
dbot.api.log.log(server, dbot.config.name, '[\u00034ERR\u000f] ' + err.message);
}
});
dbot.access = {
'admin': function(event) {
return dbot.config.admins;
},
'moderator': function(event) {
return [].concat(dbot.access.admin(event), dbot.config.moderators);
},
'power_user': function(event) {
return [].concat(dbot.access.admin(event), dbot.access.moderator(event), dbot.config.power_users);
},
'voice': function(event) {
return [].concat(dbot.access.admin(event), dbot.access.moderator(event), dbot.access.power_user(event),
_.chain(event.channel.nicks)
.filter(function(nick) {
return nick.op == true || nick.voice == true;
})
.pluck('name')
.value());
}
};
}.bind(this);
};
exports.fetch = function(dbot) {

View File

@ -2,8 +2,8 @@ var _ = require('underscore')._,
request = require('request');
var commands = function(dbot) {
return {
'~usage': function(event) {
var commands = {
'usage': function(event) {
var commandName = event.params[1];
if(_.has(dbot.usage, commandName)) {
event.reply(dbot.t('usage', {
@ -39,8 +39,8 @@ var commands = function(dbot) {
var moduleName = event.params[1];
if(!moduleName || !_.has(dbot.modules, moduleName)) {
event.reply(dbot.t('usage', {
'command': '~help',
'usage': '~help [module]'
'command': this.config.commandPrefix + 'help',
'usage': this.config.commandPrefix + 'help [module]'
}));
event.reply(dbot.t('loaded_modules', {
'modules': _.keys(dbot.modules).join(', ')
@ -48,8 +48,8 @@ var commands = function(dbot) {
} else {
var helpLink = dbot.config.repoRoot +
'blob/master/modules/' + moduleName + '/README.md';
if(dbot.config[moduleName].help) {
helpLink = dbot.config[moduleName].help;
if(dbot.config.modules[moduleName].help) {
helpLink = dbot.config.modules[moduleName].help;
}
// TODO: Check it exists
@ -60,6 +60,9 @@ var commands = function(dbot) {
}
}
};
commands['usage'].regex = [/usage ([^ ]+)/, 2];
return commands;
};
exports.fetch = function(dbot) {

View File

@ -1,6 +1,9 @@
{
"ignorable": false,
"help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md",
"dependencies": [ "event", "ignore", "users" ],
"useNickserv": false,
"dbKeys": [ "ignores", "bans" ]
"accessOutput": false,
"banOutput": false,
"passiveMode": false,
"commandPrefix": "~"
}

View File

@ -1,55 +1,78 @@
{
"command_ban": {
"en": "{user} is banned from using this command. Commence incineration.",
"es": "{user} está prohibido de usar esta instrucción. Comenzar incineración.",
"es": "{user} está prohibido de usar esta instrucción. urrently loaded modules now default: {modules}.",
"na'vi": "Tsu'ori {user} ke tung. Nga skxawng lu.",
"cy": "Mae {user} wedi ei gohurio gan ddefnyddio'r gorchymun yma. Cychwyn orfflosgiad",
"nl": "{user} mag dit commando niet meer gebruiken. Bereid het verbrandingsritueel voor.",
"de": "{user} wurde von diesem Befehl gebannt. Verbrennung einleiten"
"de": "{user} darf diesen Befehl nicht benutzen. Verbrennung einleiten",
"fr": "{user} est interdit d'utiliser cette commande. Commencer l'incinération.",
"it": "A {user} è stato interdetto di utilizzare questo commando. Iniziare incenerimento."
},
"syntax_error": {
"syntax_error": {
"en": "Invalid syntax. Initiate incineration.",
"es": "Sintaxis no válida. Iniciar incineración.",
"na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.",
"cy": "Cystrawen annilys. Cychwyn orfflosgiad",
"nl": "Ongeldige syntax. Bereid het verbrandingsritueel voor.",
"de": "Syntax ungültig. Verbrennung einleiten"
"de": "Syntax ungültig. Verbrennung einleiten",
"fr": "Syntaxe invalide. Initier l'incinération.",
"it": "Sintassi non valida. Iniziare incenerimento"
},
"usage": {
"en": "Usage for {command}: {usage}.",
"na'vi": "Nga tsun sivar ìlä {command}: {usage}.",
"cy": "Defnydd o {command}: {usage}.",
"nl": "{command} wordt op de volgende manier gebruikt: {usage}.",
"de": "Benutzung von {command}: [usage}."
"de": "Benutzung von {command}: [usage}.",
"fr": "Utilisation de {command}: {usage}.",
"it": "Utilizzo di {command}: {usage}."
},
"no_usage_info": {
"en": "No usage information found for {command}.",
"na'vi": "Oel ke tsun sivar {comamnd}it",
"cy": "Ni chanfuwyd gwybodaeth am ddefnydd o {command}",
"nl": "Geen gebruiksinformatie gevonden voor {command}.",
"de": "Keine Gebrauchsanweisung gefunden für {command}."
"de": "Keine Gebrauchsanweisung gefunden für {command}.",
"fr": "Aucune information d'utilisation trouvée pour {command}",
"it": "Nessuna informazione d' utilizzo trovata per {command}"
},
"help_link": {
"en": "Help for {module}: {link}",
"na'vi": "{module}ä srungìl {link} it tok",
"cy": "Cymorth am {module}: {link}",
"nl": "Hulp voor {module}: {link}",
"de": "Hilfe für {module}: {link}"
"de": "Hilfe für {module}: {link}",
"fr": "Aide pour {module}: {link}",
"it": "Aiuto per {module}: {link}"
},
"no_help": {
"en": "No help found for {module}.",
"na'vi": "Fì{module}ìri oel ke tsun run srungit",
"cy": "Ni chanfuwyd cymorth am {module}",
"nl": "Geen hulp gevonden voor {module}.",
"de": "Keine Hilfe gefunden für {module}."
"de": "Keine Hilfe gefunden für {module}.",
"fr": "Aucune aide trouvée pour {module}.",
"it": "Nessun aiuto trovato per {module}."
},
"loaded_modules": {
"en": "Loaded modules: {modules}.",
"cy": "Modiwlau sy'n lwythodd: {modules}.",
"nl": "Geladen modules: {modules}.",
"de": "Module geladen: {modules}."
"de": "Module geladen: {modules}.",
"fr": "Modules chargés: {modules}.",
"it": "Moduli caricati: {modules}."
},
"access_denied": {
"en": "{user}: You don't have the access level to run this command.",
"fr": "{user}: Vous n'avez pas le niveau d'accès requis pour utiliser cette commande.",
"it": "{user}: Non hai il livello d'accesso neccessario per utilizzare questo commando.",
"de": "{user}: Du hast nicht die notwendigen Rechte um diesen Befehl zu benutzen."
},
"module_commands": {
"en": "Commands in {module}: {commands}."
"en": "Commands in {module}: {commands}.",
"fr": "Commandes de {module}: {commands}.",
"it": "Commandi di {module}: {commands}.",
"de": "Befehle in {module}: {commands}."
}
}

15
modules/crypto/README.md Normal file
View File

@ -0,0 +1,15 @@
## Crypto
Cryptography!
### Description
This module calculates different hashes or ciphertexts for some algorithms.
### Commands
#### ~hash [algorithm] [text]
Calculate the hash of the given text using [algorithm].
#### ~random [number]
Gives [number] bytes of cryptographically strong pseudo-random data as hex string.

44
modules/crypto/crypto.js Normal file
View File

@ -0,0 +1,44 @@
/**
* Module Name: Crypto
* Description: Allows the magic of cryptography to take place.
*/
var cr = require('crypto');
var crypto = function(dbot) {
this.commands = {
'~hash': function(event) {
var hash = event.params[1];
try {
var h = cr.createHash(hash);
var tohash = event.params.splice(2, event.params.length-1).join(' ');
h.update(tohash);
event.reply(hash+" of \""+tohash+"\" is: "+h.digest('hex'));
} catch(err) {
event.reply(err);
}
},
'~randomdata': function(event) {
try {
var count = parseInt(event.params[1]);
if(count > 222) {
event.reply("Sorry man, I can't paste that much random data.");
return;
}
cr.randomBytes(count, function(err,buf) {
if(err) {
event.reply(err);
return;
}
event.reply(buf.toString('hex'));
});
} catch (err) {
event.reply(err);
}
}
};
};
exports.fetch = function(dbot) {
return new crypto(dbot);
};

View File

@ -0,0 +1,6 @@
{
"~md5": "~md5 [text]",
"~sha1": "~sha1 [text]",
"~sha256": "~sha256 [text]",
"~aes": "~aes \"[text]\" \"[key]\""
}

View File

@ -0,0 +1,3 @@
{
"outputChannel": "#realitree"
}

62
modules/cspeed/cspeed.js Normal file
View File

@ -0,0 +1,62 @@
var _ = require('underscore')._;
var cspeed = function(dbot) {
this.watches = dbot.db.cspeed;
this.outputChannel = dbot.config.modules.cspeed.outputChannel;
this.counts = {};
this.api = {
'getCounts': function(callback) {
callback(this.counts);
}
};
this.api['getCounts'].external = true;
this.api['getCounts'].extMap = [ 'callback' ];
this.commands = {
'addlpmwatch': function(event) {
var channel = event.params[1];
var key = event.server + '.' + channel;
if(!_.has(this.watches, key)) {
this.watches[key] = {
'server': event.server,
'channel': channel
}; // to be extended with warn nums etc
this.counts[key] = 0;
dbot.api.timers.addTimer(60000, function() {
dbot.say(event.server, this.outputChannel, channel + ' currently : ' + this.counts[key] + ' LPM');
this.counts[key] = 0;
}.bind(this));
event.reply('Added speed watch for ' + channel);
} else {
event.reply('Already watching that channel');
}
}
};
this.listener = function(event) {
var key = event.server + '.' + event.channel;
if(_.has(this.watches, key)) {
this.counts[key]++;
}
}.bind(this);
this.on = 'PRIVMSG';
this.onLoad = function() {
var watches = dbot.db.cspeed;
_.each(watches, function(watch) {
var key = watch.server + '.' + watch.channel;
this.counts[key] = 0;
dbot.api.timers.addTimer(60000, function() {
dbot.say(watch.server, dbot.db.cspeed.outputChannel, watch.channel + ': ' + this.counts[key] + 'LPM');
}.bind(this));
}.bind(this));
}.bind(this);
};
exports.fetch = function(dbot) {
return new cspeed(dbot);
};

View File

@ -1,4 +1,3 @@
{
"ignorable": true,
"help": "https://github.com/reality/depressionbot/blob/master/modules/ctcp/README.md"
"ignorable": true
}

View File

@ -1,22 +1,36 @@
var ctcp = function(dbot) {
var commands = {
"\x01VERSION\x01": function(event) {
// the current client version
event.replyNotice("\x01VERSION " + dbot.config.version + "\x01");
},
"\x01CLIENTINFO\x01": function(event){
// a list of all supported CTCP commands
event.replyNotice("\x01CLIENTINFO SOURCE VERSION USERINFO\x01");
},
"\x01SOURCE\x01": function(event){
event.replyNotice("\x01SOURCE https://github.com/reality/depressionbot\x01");
},
"\x01USERINFO\x01": function(event){
// a "witty" saying set by the user
event.replyNotice("\z01USERINFO " + dbot.config.name + "\x01");
this.listener = function(event) {
var matches = event.message.match(/\u0001[\w]+\u0001/);
if(matches) {
// We need the CTCP command
var question = matches[0];
// Cut \u0001 characters from command
question = question.slice(1,question.length-1);
switch(question) {
case 'CLIENTINFO':
event.replyNotice("\u0001CLIENTINFO SOURCE VERSION USERINFO\u0001");
break;
case 'FINGER':
event.replyNotice("\u0001FINGER STOP FINGERING ME BRO\u0001");
break;
case 'SOURCE':
event.replyNotice("\u0001SOURCE "+dbot.config.repoRoot+"\u0001");
break;
case 'TIME':
var d = new Date();
event.replyNotice("\u0001TIME "+d.toISOString()+"\u0001");
break;
case 'USERINFO':
event.replyNotice("\u0001USERINFO "+dbot.config.name+"\u0001");
break;
case 'VERSION':
event.replyNotice("\u0001VERSION "+dbot.config.version+"\u0001");
break;
default:
event.replyNotice("\u0001"+question+" Idk what you want. Try CLIENTINFO.\u0001");
}
}
}
this.commands = commands;
};
this.on = 'PRIVMSG';
};

View File

@ -1,8 +1,8 @@
{
"username": "youruserhere",
"password": "yourpasswordhere",
"dependencies": [ "command" ],
"dependencies": [ "link" ],
"ignorable": true,
"help": "https://github.com/reality/depressionbot/blob/master/modules/dent/README.md",
"dentQuotes": false
"dentQuotes": true,
"api": "http://quitter.se/"
}

View File

@ -2,7 +2,6 @@ var request = require('request');
_ = require('underscore')._;
var dent = function(dbot) {
this.dbot = dbot;
this.StatusRegex = {
identica: /\bhttps?:\/\/identi\.ca\/notice\/(\d+)\b/ig,
twitter: /\bhttps?:\/\/twitter\.com\/\w+\/status\/(\d+)\b/ig
@ -15,14 +14,14 @@ var dent = function(dbot) {
this.api = {
'post': function(content) {
var username = dbot.config.dent.username,
password = dbot.config.dent.password,
var username = this.config.username,
password = this.config.password,
info,
auth = "Basic " +
new Buffer(username + ":" + password).toString("base64");
request.post({
'url': 'http://identi.ca/api/statuses/update.json?status=' +
'url': this.config.api + '/statuses/update.json?status=' +
escape(content),
'headers': {
'Authorization': auth
@ -34,7 +33,7 @@ var dent = function(dbot) {
}
};
this.lookup = function(event, id, service) {
this.lookup = function(id, service, callback) {
request({
url: this.StatusAPI[service],
qs: {"id": id},
@ -42,7 +41,7 @@ var dent = function(dbot) {
}, function(error, response, body) {
if (!error && response.statusCode == 200) {
if (_.has(body, 'text')) {
event.reply(service + " [" + body.user.screen_name + '] ' + body.text);
callback(service + " [" + body.user.screen_name + '] ' + body.text);
}
}
});
@ -54,11 +53,11 @@ var dent = function(dbot) {
event.reply('Dent posted (probably).');
}
};
this.commands['~dent'].regex = [/^~dent (.+)$/, 2];
this.commands['~dent'].regex = [/^dent (.+)$/, 2];
this.onLoad = function() {
if(dbot.config.dent.dentQuotes === true && _.has(dbot.modules, 'quotes')) {
dbot.api.command.addHook('~qadd', function(key, text) {
if(this.config.dentQuotes === true && _.has(dbot.modules, 'quotes')) {
dbot.api.event.addHook('qadd', function(key, text) {
if(text.indexOf('~~') == -1) {
this.api.post(key + ': ' + text);
}
@ -66,8 +65,8 @@ var dent = function(dbot) {
}
for(s in this.StatusRegex) {
dbot.api.link.addHandler(s, this.StatusRegex[s], function(event, matches, name) {
this.lookup(event, matches[1], name);
dbot.api.link.addHandler(s, this.StatusRegex[s], function(matches, name, callback) {
this.lookup(matches[1], name, callback);
}.bind(this));
}
}.bind(this);

View File

@ -17,14 +17,14 @@ var parseDiceSpec = function (specString) {
var normalizeDiceSpec = function (specString) {
var diceSpec = parseDiceSpec(specString);
if (diceSpec["sides"] > 10000) {
return false;
}
if (diceSpec["count"] > 1000) {
return false;
}
if (diceSpec["sides"] > 10000) {
return false;
}
if (diceSpec["count"] > 1000) {
return false;
}
if (diceSpec["count"] > 1) {
var count = diceSpec["count"];
} else {
@ -74,7 +74,7 @@ var dice = function(dbot) {
event.reply(rolls[i][0] + ": invalid dice spec");
} else {
if (rolls[i][1].length > 1) {
var total = " (total " + rolls[i][1].sum();
var total = " (total " + _.reduce(rolls[i][1], function(memo, num){ return memo + num; }, 0);
if (rolls[i][2] != 0) {
if (rolls[i][2] > 0) {
total += " + ";

View File

@ -1,3 +0,0 @@
{
"help": "https://github.com/reality/depressionbot/blob/master/modules/dns/README.md"
}

View File

@ -2,13 +2,40 @@
* Module Name: DNS
* Description: Performs and reports on basic DNS functions.
*/
var dnsmod = require('dns');
var dnsm = require('dns'),
request = require('request'),
http = require('http');
var dns = function(dbot) {
if(!_.has(dbot.db, 'ip')) {
dbot.db.ip = {};
}
var ips = dbot.db.ip;
this.api = {
'getGeoIp': function(ip, callback) {
if(_.has(ips, ip)) {
body = ips[ip];
callback(ip + ' is located in '+ body.city + ', ' + body.country + '. Hostname: ' + body.hostname + '. ISP: ' + body.org);
} else {
request.get('http://ipinfo.io/'+ip, {
'json': true
}, function(err, res, body) {
if(!err && body) {
callback(ip + ' is located in '+ body.city + ', ' + body.country + '. Hostname: ' + body.hostname + '. ISP: ' + body.org);
} else {
callback('No info about ' + ip);
}
ips[ip] = body;
});
}
}.bind(this)
};
var commands = {
'~lookup': function(event) {
domain = event.params[1];
dnsmod.lookup(domain, function (error, addr) {
dnsm.lookup(domain, function (error, addr) {
if (error) {
event.reply(dbot.t("lookup-error",{"domain": domain, "code": error.code}));
} else {
@ -16,20 +43,52 @@ var dns = function(dbot) {
}
});
},
'~rdns': function(event) {
ip = event.params[1];
dnsmod.reverse(ip, function (error, domain) {
dnsm.reverse(ip, function (error, domain) {
if (error) {
event.reply(dbot.t("rdns-error",{"domain": domain, "ip": ip, "error": error.code}));
} else {
event.reply(dbot.t("rdns",{"domain": domain, "ip": ip}));
}
});
},
'~geoip': function(event) {
var ip = event.params[1];
this.api.getGeoIp(ip, function(result) { event.reply(result); });
},
'~dnsbl': function(event) {
var revIp = event.input[1].trim().split('.').reverse().join('.');
dnsm.lookup(revIp + '.cbl.abuseat.org', function(err, res) {
if(!err && res) {
event.reply(event.input[1] + ' is listed as an abusive IP.');
} else {
event.reply(event.input[1] + ' does not seem to be a Naughty Nancy.');
}
});
}
};
commands['~dnsbl'].regex = [/^dnsbl ([\d\w\s\.-]*)/, 2];
this.commands = commands;
this.on = 'PRIVMSG';
if(dbot.config.modules.dns.dnsblconn == true) {
this.listener = function(event) {
if(event.message.match('CLICONN')) {
var ip = event.message.match('CLICONN ([^ ]+).*?((?:[0-9]{1,3}\.){3}[0-9]{1,3}) users');
revIp = ip[2].trim().split('.').reverse().join('.');
dbot.say(event.server, '#dnsbl', 'DEBUG: Looking up ' + ip[2] + ' for ' + ip[1] + ' @ ' + revIp);
dnsm.lookup(revIp + '.cbl.abuseat.org', function(err, res) {
if(!err && res) {
dbot.say(event.server, '#dnsbl', 'ALERT: ' + ip[1] + ' connecting from ' + ip[2] + ' may well be NAUGHTY.');
}
});
}
}
this.on = 'NOTICE';
}
};
exports.fetch = function(dbot) {

View File

@ -3,21 +3,30 @@
"en": "{domain} is \u000303AVAILABLE! \u000314({code})",
"cy": "{domain} \u000303AR GAEL! \u000314({code})",
"nl": "{domain} is \u000303BESCHIKBAAR! \u000314({code})",
"de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})"
"de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})",
"fr": "{domain} est \u000303DISPONIBLE! \u000314({code})",
"it": "{domain} è \u000303DISPONIBILE! \u000314({code})"
},
"lookup": {
"en": "{domain} is \u000305TAKEN! \u000314({address})",
"cy": "Dydy {domain} \u000305DDIM AR GAEL! \u000314({address})",
"nl": "{domain} is \u000305BEZET! \u000314({address})",
"de": "{domain} ist \u000305BELEGT! \u000314({address})"
"de": "{domain} ist \u000305BELEGT! \u000314({address})",
"fr": "{domain} est \u000305PRIS! \u000314({address})",
"it": "{domain} èt \u000305RISERVATO! \u000314({address})"
},
"rdns": {
"en": "{ip} \u2192 {domain}"
"en": "{ip} \u2192 {domain}",
"fr": "{ip} \u2192 {domain}",
"it": "{ip} \u2192 {domain}",
"de":"{ip} \u2192 {domain}"
},
"rdns-error": {
"en": "Unable to lookup {ip}. \u000314({error})",
"cy": "Methu am-edrych {ip}. \u000314({error})",
"nl": "{ip} kan niet worden opgezocht. \u000314({error})",
"de": "Kann {ip} nicht auflösen. \u000314({error})"
"de": "Kann {ip} nicht auflösen. \u000314({error})",
"fr": "Impossible de rechercher {ip}. \u000314({error})",
"it": "Non è possibile cercare {ip}. \u000314({error})"
}
}

View File

@ -1,3 +0,0 @@
{
"help": "https://github.com/reality/depressionbot/blob/master/modules/event/README.md"
}

View File

@ -1,3 +0,0 @@
{
"help": "https://github.com/reality/depressionbot/blob/master/modules/flashy/README.md"
}

View File

@ -37,7 +37,7 @@ var flashy = function(dbot) {
}
};
this.commands['~flashy'].regex = [/^~flashy ([^ ]+) (.+)$/, 3];
this.commands['~flashy'].regex = [/^flashy ([^ ]+) (.+)$/, 3];
};
exports.fetch = function(dbot) {

View File

@ -10,7 +10,7 @@ var pages = function(dbot) {
res.render('flashy', {
'name': dbot.config.name,
'colour': colour,
'text': req.params.text
'text': decodeURIComponent(req.params.text)
});
}
};

4
modules/food/config.json Normal file
View File

@ -0,0 +1,4 @@
{
"outputPrefix": "\u000311food\u000f",
"api_key": "http://food2fork.com/about/api"
}

60
modules/food/food.js Normal file
View File

@ -0,0 +1,60 @@
/**
* Module name: Food
* Description: recipe search
*/
var _ = require('underscore')._,
request = require('request');
var food = function(dbot) {
this.commands = {
'~recipe': function(event) {
request.get('http://food2fork.com/api/search', {
'qs': {
'key': this.config.api_key,
'q': event.input[1]
},
'json': true
}, function(error, response, body) {
if(_.isObject(body) && _.has(body, 'recipes') && body.recipes.length > 0) {
var num = _.random(0, body.recipes.length - 1),
recipe = body.recipes[num];
event.reply(dbot.t('recipe', {
'title': recipe.title,
'link': recipe.source_url
}));
} else {
event.reply(dbot.t('no_recipe'));
}
}.bind(this));
}
};
this.commands['~recipe'].regex = [/^recipe (.+)$/, 2];
this.listener = function(event) {
var match = event.message.match(new RegExp(dbot.config.name + ': what should i (have|eat|make)\\??( for (dinner|lunch|breakfast))?\\??', 'i'));
if(match) {
var page = _.random(0, 200);
request.get('http://food2fork.com/api/search', {
'qs': {
'key': this.config.api_key,
'page': page
},
'json': true
}, function(error, response, body) {
if(_.isObject(body) && _.has(body, 'recipes') && body.recipes.length > 0) {
var num = _.random(0, body.recipes.length - 1),
recipe = body.recipes[num];
event.reply(event.user + ': You should make ' + recipe.title + '. See: ' + recipe.source_url);
}
}.bind(this));
}
}.bind(this);
this.on = 'PRIVMSG';
};
exports.fetch = function(dbot) {
return new food(dbot);
};

View File

@ -0,0 +1,8 @@
{
"recipe": {
"en": "{title} - {link}"
},
"no_recipe": {
"en": "No recipes found."
}
}

34
modules/fpx/README.md Normal file
View File

@ -0,0 +1,34 @@
## 500px
Adds various 500px functionality.
### Description
This module provides a command which allows users to search for a random popular 500px photo.
### Dependencies
It has following dependencies:
+ [node-500px](https://github.com/ro-ka/node-500px)
### config.json
ignorable and consumerKey has to be configurated. It can be obtained at http://developers.500px.com
```
{
"ignorable": true,
"api_key": "CONSUMERKEY_HERE"
}
```
### Commands
~r500px
Responds with a random popular 500px photo.
Example:
+ ~r500px
### TODO
Photo by user etc.

4
modules/fpx/config.json Normal file
View File

@ -0,0 +1,4 @@
{
"ignorable": true,
"api_key": "CONSUMERKEY_HERE"
}

33
modules/fpx/fpx.js Normal file
View File

@ -0,0 +1,33 @@
/**
* Module Name: 500px
* Description: Adds various 500px functionality.
* Requires: node-500px [http://mjgil.github.io/five-px/]
*/
var _ = require('underscore')._,
API500px = require('500px').API500px;
var fpx = function(dbot) {
this.commands = {
'~r500px': function(event) {
var random = Math.floor(Math.random() * 30);
this.api500px.photos.getPopular({'sort': 'created_at', 'rpp': '30'}, function(error, results) {
if (error) {
event.reply(dbot.t('5px_error'));
console.log(error);
} else {
var name = results.photos[random].name,
id = results.photos[random].id;
event.reply(dbot.t('5px_result',{'name':name,'id':id}));
}
});
}
};
this.onLoad = function() {
this.api500px = new API500px(this.config.api_key);
}.bind(this);
};
exports.fetch = function(dbot) {
return new fpx(dbot);
};

8
modules/fpx/strings.json Normal file
View File

@ -0,0 +1,8 @@
{
"5px_result":{
"en": "{name} - http://500px.com/photo/{id}"
},
"5px_error": {
"en": "Something went wrong :( Example: '~r500px'"
}
}

3
modules/fpx/usage.json Normal file
View File

@ -0,0 +1,3 @@
{
"~r500px": "~r500px"
}

@ -1 +0,0 @@
Subproject commit 5f4e3dc8335000e97af528fee289b880a3c99e81

18
modules/github/LICENSE Normal file
View File

@ -0,0 +1,18 @@
Copyright (c) 2013 Douglas Gardner <douglas@chippy.ch>
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.

28
modules/github/README.md Normal file
View File

@ -0,0 +1,28 @@
## Github
Grabs interesting data from the GitHub API.
### Description
This module for [depressionbot](https://github.com/reality/depressionbot) takes some interesting information about Github and parses it in a pleasing manner.
### Configuration
#### defaultrepo
When repository information is lacking from the command, this repository will be used.
#### sortorder
Defines the behaviour of ~issue when no arguments are given. Options are ``created``, ``updated``, or ``comments``.
### Commands
#### ~commits
Returns the number of commits in the repository of the current depressionbot instance.
#### ~gstatus
Returns the [current status of Github](https://status.github.com), and a message explaining the current state of affairs.
#### ~issue (user/repo) [id]
Gives information about the isse pecified, from the default repository if one is not explicitly stated.
#### ~milestone [milestone name]
Returns milestone progress for any given milestone, with a link to the milestone in question.
#### ~repo (repo name)
Returns information about the repo given as a parameter. The repo should be specified as ``user/name``; for example, ``twitter/snowflake``.
#### ~repocount [user]
Returns the number of public Github repositories for the specified user.
### Dependencies
* [request](https://github.com/mikeal/request/):``$ npm install request``

View File

@ -0,0 +1,8 @@
{
"dependencies": [ "command" ],
"ignorable": true,
"help": "http://github.com/zuzak/dbot-github/blob/master/README.md",
"defaultrepo": "reality/dbot",
"sortorder": "updated",
"useragent": "reality/depressionbot github module"
}

192
modules/github/github.js Normal file
View File

@ -0,0 +1,192 @@
/**
* Module Name: Github
* Description: Retrieves interesting Github information
*/
var request = require('request'),
exec = require('child_process').exec;
var github = function(dbot) {
this.api = {
"githubStatus": function(callback){
var reqUrl = "https://status.github.com/api/last-message.json";
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
callback(JSON.parse(body));
});
}
};
var commands = {
'~repocount': function(event) {
var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos";
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
if(response.statusCode == "200") {
var result = JSON.parse(body);
event.reply(dbot.t("repocount",{"user": event.params[1], "count": result.length}));
} else {
event.reply(dbot.t("usernotfound"));
}
});
},
'~repo': function(event) {
var repo = event.params[1];
if (typeof repo == 'undefined') {
repo = this.config.defaultrepo;
}
var reqUrl = "https://api.github.com/";
reqUrl += "repos/" + repo;
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
var data = JSON.parse(body);
if (data["fork"]) {
event.reply(dbot.t("forkedrepo",data));
} else {
event.reply(dbot.t("unforkedrepo",data));
}
// TODO: move this shizz into an api call
var longurl = "http://github.com/" + repo;
event.reply(dbot.t('location')+" "+longurl);
});
},
'~gstatus': function(event) {
data = this.api.githubStatus(function(data){
event.reply(dbot.t("status"+data["status"]));
event.reply(data["body"]);
}.bind(this));
},
'~milestone': function(event) {
var repo = this.config.defaultrepo;
var name = event.params[1];
if (event.params[2]){
repo = name;
name = event.params[2];
}
var reqUrl = "https://api.github.com/repos/";
reqUrl += repo + "/milestones";
request({"url": reqUrl, "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) {
var data = JSON.parse(body);
for (var section in data) {
var milestone = data[section];
if (milestone["title"] == name){
var str = "Milestone " + milestone["title"];
var progress = milestone["closed_issues"] / (milestone["open_issues"] + milestone["closed_issues"]);
progress = Math.round(progress*100);
var bar = "[";
for (var i = 10; i < 100; i += 10) {
if ((progress/i) > 1) {
bar += "█";
} else {
bar += " ";
}
}
bar += "]";
str += " is " + bar + progress + "% complete";
event.reply(str);
break;
}
}
});
},
'~repocount': function(event) {
// TODO: add handling for non existent user
var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos";
request({"url": reqUrl,"headers": { "User-Agent": this.config.useragent}}, function(error, response, body) {
var result = JSON.parse(body);
event.reply(event.params[1] + " has " + result.length + " public repositories.");
});
},
'~grate': function(event) {
request.get({"url":"https://api.github.com/rate_limit", "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) {
var data = JSON.parse(body);
if (data.message){
event.reply(data.message);
} else {
event.reply(data.rate.remaining + " requests of " + data.rate.limit + " remaining.");
}
});
},
'~issue': function(event) {
var repo, issue, randflag;
if (isNaN(event.params[1]) && event.params[1]){ // if ~issue foo/bar
repo = event.params[1];
issue = event.params[2];
} else {
repo = this.config.defaultrepo;
issue = event.params[1];
}
if (issue == "*" || issue == "random" || issue == "0") {
issue = "";
randflag = true;
} else if (!issue) { // issue is undefined
issue = "";
} else {
issue = "/" + issue; // got to be a better way
}
var reqUrl = "https://api.github.com/repos/" + repo + "/issues" +
issue + "?sort=" + this.config.sortorder;
request.get({"url": reqUrl, headers: { "User-Agent": this.config.useragent}}, function(error,response, body) {
if (response.statusCode == "200") {
var data = JSON.parse(body);
if (!issue){
if (randflag) {
data = data[Math.floor(Math.random() * data.length)];
} else {
data = data[0];
}
}
if (_.has(data["pull_request"], "html_url")){
data["pull_request"] = " with code";
} else {
data["pull_request"] = "";
}
if (data["state"]=="open") {
data["state"] = "\u000303" + data["state"];
} else {
data["state"] = "\u000304" + data["state"];
}
var labels = "";
for (var i=0; i < data["labels"].length; i++) { // for-in doesn't like me
var color = "\u0003" + (parseInt(data["labels"][i]["color"],16) % 15);
labels += " " + color + data["labels"][i]["name"];
}
data["label"] = labels;
event.reply(dbot.t("issue",data));
event.reply(data["html_url"]);
} else {
event.reply(dbot.t("issuenotfound"));
}
});
},
'~commits': function(event) {
exec("git rev-list --all | wc -l", function(error, stdout, stderr) {
stdout = stdout.trim();
request({"url":"http://numbersapi.com/" + stdout + "?fragment&default=XXX"}, function(error, response, body){
if (body != "XXX"){
event.reply(dbot.t("commitcountfun",{"fact": body, "count": stdout}));
} else {
// nothing fun about the number, let's try the year
request({"url":"http://numbersapi.com/" + stdout + "/year?fragment&default=XXX"}, function(error, response, body){
if (body != "XXX"){
event.reply(dbot.t("commitcountyear",{"fact": body, "count": stdout}));
} else {
event.reply(dbot.t("commitcountboring",{"count": stdout}));
}
});
}
});
});
}
};
this.commands = commands;
this.on = 'PRIVMSG';
};
exports.fetch = function(dbot) {
return new github(dbot);
};

View File

@ -0,0 +1,94 @@
{
"repocount": {
"en": "{user} has {count} public repos.",
"cy": "Mae {count} archifdai cyhoeddus gan {user}.",
"de": "{user} hat {count} öffnetliche Repos.",
"fr": "{user} a {count} dépôt(s) public(s).",
"it": "{user} ha {count} deposito/i pubblico/i."
},
"statusgood": {
"en": "\u000309Shit's fine",
"cy": "\u000309Cachu'n ddirwy",
"de": "\u000309Alles in Ordnung",
"fr": "\u000309Cette merde tourne bien",
"it": "\u000309Funziona a meraviglia."
},
"statusminor": {
"en": "\u000308Shit's touchy",
"cy": "\u000308Cachu'n fregus",
"de": "\u000308Kleinere Probleme vorhanden",
"fr": "\u000308Cette merde a un petit problème",
"it": "\u000308Piccoli problemi all' orizzonte"
},
"statusmajor": {
"en": "\u000304Shit's fucked:",
"cy": "\u000304Cachu wedi cyrraedd y ffan:",
"de": "\u000304Du bist am Arsch",
"fr": "\u000304Cette merde est foutue : ",
"it": "\u000304Sei nella merda : "
},
"location": {
"en": "You can find that shit at:",
"cy": "Gallwch ddod o hyd y cachu yn:",
"de": "Kann gefunden werden unter:",
"fr": "Tu peux trouver cette merde ici : ",
"it": "Puoi trovare questa coglionata a: "
},
"forkedrepo": {
"en": "{name} is a forked {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]",
"cy": "{name} ydy archif {language} fforchog gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]",
"de": "{name} ist eine geteilte {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]",
"fr": "{name} est un dépôt fourché {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]",
"it": "{name} è un deposito biforcato {language} con {open_issues} problema/i irrisolto/i [{forks}F {watchers}W]"
},
"unforkedrepo": {
"en": "{name} is a {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]",
"cy": "{name} ydy archif {language} gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]",
"de": "{name} ist eine {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]",
"fr": "{name} est un dépôt {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]",
"it": "{name} è un deposito {language} con {open_issues} problema/i irrisolto/i [{forks}F {watchers}W]"
},
"usernotfound": {
"en": "User not found.",
"cy": "Defnyddiwr heb ei ganfod.",
"de": "Benutzer nicht gefunden.",
"fr": "Utilisateur non trouvé.",
"it": "Utente non trovato."
},
"issuenotfound": {
"en": "Unable to find that issue.",
"cy": "Wedi methu dod o hyd mater hwnnw",
"de": "Kann dieses Problem nicht finden.",
"fr": "Impossible de trouver ce problème.",
"it": "Impossibile trovare questo problema."
},
"issue": {
"en": "Issue \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}",
"cy": "Mater \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} sylwadau]{label}",
"de": "Problem \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}",
"fr": "Problème \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} commentaires]{label}",
"it": "Problema \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} commento/i]{label}"
},
"commitcountboring": {
"en": "My code has been committed {count} times.",
"cy": "Mae fy cod wedi cael ei gyflawni ar {count} adegau.",
"de": "Mein Code wurde {count} mal bestätigt.",
"fr": "Mon code a été modifié {count} fois.",
"it": "Il mio codice è stato modificato {count} volta/e."
},
"commitcountfun": {
"en": "My repository has the same number of commits as {fact} ({count}).",
"cy": "Yr un nifer o ymrwymo fel {fact} gan fy archif ({count}).",
"de": "Meine Repository hat die gleiche Anzahl Commits wie {fact} ({count}).",
"fr": "Mon dépôt a le même nombre de modifications que {fact} ({count}).",
"it": "Il mio deposito ha lo stesso numero di modifiche come {fact} ({count})."
},
"commitcountyear": {
"en": "My repository's commits number {count}, the year that {fact}.",
"cy": "Nifer o ymrwymo gan fy archif: {count}, y flwyddyn y {fact}.",
"de": "Anzahl der Commits in meinem Repository {count}, des Jahres {fact}",
"fr": "Mon dépot compte {count} modifications, l'année où {fact}.",
"it": "Il mio deposito ha {count} modifica/che, l' anno che {fact}."
}
}

29
modules/gmaps/gmaps.js Normal file
View File

@ -0,0 +1,29 @@
/**
* Module Name: Google Maps
* Description: GMaps and ting
*/
var gm = require('googlemaps'),
_ = require('underscore')._;
var gmaps = function(dbot) {
this.commands = {
'~from': function(event) {
var from = event.input[1],
to = event.input[2],
departureNow = Math.floor((new Date()).getTime()/1000);
gm.directions(from, to, function(err, result) {
if(!err && result && result.status !== 'ZERO_RESULTS') {
event.reply('If you leave right now, it will take ' + result.routes[0].legs[0].duration.text + ' to get from ' + from + ' to ' + to + ' via public transport.');
} else {
event.reply('Apparently one cannot get from ' + from + ' to ' + to + ' using public transport. Do you accept the challenge?');
}
}, 'false', 'transit', null, null,null, null, null, departureNow);
}
};
this.commands['~from'].regex = [/^from (.*) to (.*)/, 3];
};
exports.fetch = function(dbot) {
return new gmaps(dbot);
};

View File

@ -0,0 +1,4 @@
{
"api_key": "sethere",
"outputPrefix": "\u00033goodreads\u000f"
}

View File

@ -0,0 +1,293 @@
/**
* Module Name: GoodReads
* Description: Interacts with the GoodReads API to provide book-oriented functionality to dbot
*/
var util = require('util'),
_ = require('underscore')._,
rp = require('request-promise-native'),
parseString = util.promisify(require('xml2js').parseString);
var GoodReads = function(dbot) {
this.apiRoot = 'https://www.goodreads.com';
this.internalAPI = {
'outputError': (evt, e) => {
switch(e) {
case 'goodreads-error': evt.reply('Error talking to GoodReads.'); return;
case 'book-not-found': evt.reply(dbot.t('gr_nobook')); return;
case 'no-description': evt.reply('No description was found for the book you asked for.'); return;
case 'author-not-found': evt.reply(dbot.t('gr_noauthor')); return;
}
console.log(e);
evt.reply('Something went wrong and I don\'t know what.');
},
'formatProfile': profile => {
var shelves = {};
_.each(profile.user_shelves.user_shelf, shelf => {
shelves[shelf.name] = shelf.book_count['_'];
});
profile.user_shelves = shelves;
return profile;
}
};
this.api = {
'findBook': async term => {
//https://www.goodreads.com/search/index.xml
var body = await rp({
uri: this.apiRoot + '/search/index.xml',
qs: {
key: this.config.api_key,
q: term.split(' ').join('+')
}
});
var response = await parseString(body, { explicitArray: false });
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
var result = response.GoodreadsResponse.search.results;
if(!result || !_.has(result, 'work')) throw 'book-not-found';
if(!result.work[0]) throw 'book-not-found';
return {
id: result.work[0].best_book.id['_'],
title: result.work[0].best_book.title,
author: result.work[0].best_book.author.name,
rating: result.work[0].average_rating
};
},
'getSummaryForBook': async id => {
//https://www.goodreads.com/book/show.xml
var body = await rp({
uri: this.apiRoot + '/book/show.xml',
qs: {
key: this.config.api_key,
id: id
}
});
var response = await parseString(body, { explicitArray: false });
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
var result = response.GoodreadsResponse.book;
if(!result) throw 'book-not-found';
if(!_.has(result, 'description')) throw 'no-description';
return result.description;
},
'findAuthor': async term => {
//https://www.goodreads.com/api/author_url/<ID>
var body = await rp({
url: this.apiRoot + '/api/author_url/' + term,
qs: {
key: this.config.api_key
}
});
var response = await parseString(body, {explicitArray: false });
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
var result = response.GoodreadsResponse.author;
if(!result) throw 'author-not-found';
return {
id: result['$'].id,
author: result.name
};
},
'getProfileById': async id => {
//https://www.goodreads.com/user/show.xml
try {
var body = await rp({
url: this.apiRoot + '/user/show.xml',
qs: {
key: this.config.api_key,
id: id
}
});
}
catch (e) {
if(e.statusCode && e.statusCode == 404) {
throw 'user-not-found';
return;
}
throw e;
}
var response = await parseString(body, { explicitArray: false });
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
var result = response.GoodreadsResponse.user;
if(!result) throw 'user-not-found';
return this.internalAPI.formatProfile(result);
},
'getProfileByName': async username => {
//https://www.goodreads.com/user/show.xml
try {
var body = await rp({
url: this.apiRoot + '/user/show.xml',
qs: {
key: this.config.api_key,
username: username
}
});
}
catch (e) {
if(e.statusCode && e.statusCode == 404) {
throw 'user-not-found';
return;
}
throw e;
}
var response = await parseString(body, { explicitArray: false });
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
var result = response.GoodreadsResponse.user;
if(!result) throw 'user-not-found';
return this.internalAPI.formatProfile(result);
},
'getShelfForUserId': async (id, shelf) => {
//https://www.goodreads.com/review/list.xml?v=2
var body = await rp({
url: this.apiRoot + '/review/list.xml',
qs: {
v: '2',
key: this.config.api_key,
id: id,
shelf: shelf
}
});
var response = await parseString(body, { explicitArray: false });
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
let result = response.GoodreadsResponse.reviews.review;
if(!result) return [];
if(!_.isArray(result)) {
result = [result];
}
return _.map(result, r => {
return {
id: r.book.id['_'],
title: r.book.title_without_series
};
});
}
};
this.commands = {
'~book' : async evt => {
try {
var book = await this.api.findBook(evt.input[1]);
evt.reply(dbot.t('gr_book', {
author: book.author,
title: book.title,
rating: book.rating,
link: this.apiRoot + '/book/show/' + book.id
}));
}
catch(e) { this.internalAPI.outputError(evt, e); }
},
'~booksummary': async evt => {
try {
var book = await this.api.findBook(evt.input[1]);
var summary = await this.api.getSummaryForBook(book.id);
evt.reply(dbot.t('gr_summary', {
title: book.title,
summary: summary,
link: this.apiRoot + '/book/show/' + book.id
}));
}
catch(e) { this.internalAPI.outputError(evt, e); }
},
'~author' : async evt => {
try {
evt.reply(dbot.t('gr_author', await this.api.findAuthor(evt.input[1])));
}
catch(e) { this.internalAPI.outputError(evt, e); }
},
'~reading': async (evt, profile) => {
try {
let books = await this.api.getShelfForUserId(profile.id, 'currently-reading');
var booksCount = books.length;
if(!booksCount) {
evt.reply(dbot.t('gr_not_reading', { user: evt.rUser.currentNick }));
return;
}
let tooMany = booksCount > 5;
if (tooMany) books = _.sample(books, 5);
evt.reply(dbot.t('gr_is_reading', { user: evt.rUser.currentNick, count: booksCount }));
_.each(books, b => {
evt.reply(ostr = b.title + ' - https://www.goodreads.com/book/show/' + b.id);
});
if (tooMany) {
evt.reply('... And ' + (booksCount - 5) + ' more - https://www.goodreads.com/review/list/' + profile.id + '?shelf=currently-reading');
}
}
catch(e) { this.internalAPI.outputError(evt, e); }
}
};
this.commands['~book'].regex = [/^book (.*)/, 2];
this.commands['~booksummary'].regex = [/^booksummary (.*)/, 2];
this.commands['~author'].regex = [/^author ([\d\w\s-]*)/, 2];
this.commands['~reading'].requiresProfile = true;
_.each(this.commands, ((cmd, cmdName) => {
if(cmd.requiresProfile) {
this.commands[cmdName] = (async evt => {
var grUsername = evt.rProfile.goodreads;
if(!grUsername) {
evt.reply(evt.rUser.currentNick + ': Set a Goodreads username with "~set goodreads username"');
return;
}
let grId = evt.rProfile.goodreads_id;
try {
var profile;
if(grId) {
profile = await this.api.getProfileById(grId);
} else {
profile = await this.api.getProfileByName(grUsername);
grId = profile.id;
dbot.api.profile.setProperty(evt.server, evt.user, 'goodreads_id', grId, function(){});
}
await cmd(evt, profile);
}
catch(e) {
if(e === 'user-not-found') evt.reply('User not found. Is your GoodReads username set correctly?');
else this.internalAPI.outputError(evt, e);
}
}).bind(this);
}
}).bind(this))
}
exports.fetch = dbot => new GoodReads(dbot);

View File

@ -0,0 +1,23 @@
{
"gr_book": {
"en": "[{title} by {author} - {rating}] - {link}"
},
"gr_summary": {
"en": "[{title}] - {summary} - {link}"
},
"gr_author": {
"en": "[{author}] - https://www.goodreads.com/author/show/{id}"
},
"gr_nobook": {
"en": "No book by that name was found."
},
"gr_noauthor": {
"en": "No author by that name was found."
},
"gr_not_reading": {
"en": "{user} is not currently reading any books."
},
"gr_is_reading": {
"en": "{user} is currently reading the following {count} books:"
}
}

View File

@ -0,0 +1,6 @@
{
"~book": "~book [bookname] - returns the title, author, rating, and GoodReads link",
"~booksummary": "~booksummary [bookname] - returns the summary for the requested book",
"~author": "~author [authorname] - returns the GoodReads link for the requested author",
"~reading": "~reading - displays up to 5 of the books you are currently reading"
}

49
modules/ignore/api.js Normal file
View File

@ -0,0 +1,49 @@
var _ = require('underscore')._;
var api = function(dbot) {
return {
// Is user ignoring command/module?
'isUserIgnoring': function(user, item, callback) {
this.internalAPI.isUserImpeded(user, item, 'ignores', callback);
},
// Is user banned from command/module?
'isUserBanned': function(user, item, callback) {
this.internalAPI.isUserImpeded(user, item, 'bans', callback);
},
// Is channel ignoring module?
// TODO: Command support
'isChannelIgnoring': function(channelName, item, callback) {
var isIgnoring = false,
channel = false;
this.db.search('channel_ignores', {
'server': server,
'name': channel
}, function(result) {
channel = result;
}, function(err) {
if(!err && channel && _.include(channel.ignores, item)) {
isIgnoring = true;
}
callback(isIgnoring);
});
},
// Resolve a nick and return their user and ignores object
'getUserIgnores': function(user, callback) {
this.db.read('ignores', user.id, function(err, ignores) {
if(!err && ignores) {
callback(false, ignores);
} else {
callback(true, null);
}
});
}
};
}
exports.fetch = function(dbot) {
return api(dbot);
};

View File

@ -1,6 +1,6 @@
{
"ignorable": false,
"dependencies": [ "command" ],
"dependencies": [ "users" ],
"dbKeys": [ "ignores", "bans" ],
"help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md"
"dbType": "redis"
}

View File

@ -5,15 +5,35 @@
* this information, since that actually performs the ignorance. Also provides
* commands for moderators to choose the bot to ignore certain channels.
*/
var _ = require('underscore')._;
var _ = require('underscore')._,
databank = require('databank'),
uuid = require('node-uuid'),
NoSuchThingError = databank.NoSuchThingError;
var ignore = function(dbot) {
this.internalAPI = {
'isUserImpeded': function(user, item, by, callback) {
this.api.getUserIgnores(user, function(err, ignores) {
var isImpeded = false;
if(!err && ignores) {
if(_.has(dbot.commands, item) && !_.include(ignores[by], item)) {
item = dbot.commands[item].module;
}
if(_.include(ignores[by], item) || _.include(ignores[by], '*')) {
isImpeded = true;
}
}
callback(isImpeded);
});
}.bind(this)
};
var commands = {
'~ignore': function(event) {
var module = event.params[1];
var ignorableModules = _.chain(dbot.modules)
.filter(function(module, name) {
return dbot.config[module].ignorable === true;
return dbot.config.modules[module].ignorable === true;
})
.pluck('name')
.value();
@ -25,21 +45,30 @@ var ignore = function(dbot) {
}));
} else {
if(module == '*' || _.include(ignorableModules, module)) {
if(_.has(dbot.db.ignores, event.user) && _.include(dbot.db.ignores[event.user], module)) {
event.reply(dbot.t('already_ignoring', { 'user': event.user }));
} else {
if(_.has(dbot.db.ignores, module)) {
dbot.db.ignores[event.user].push(module);
} else {
dbot.db.ignores[event.user] = [module];
this.api.getUserIgnores(event.rUser, function(err, ignores) {
if(!ignores) {
ignores = {
'id': event.rUser.id,
'ignores': [],
'bans': []
};
}
dbot.instance.ignoreTag(event.user, module);
event.reply(dbot.t('ignored', {
'user': event.user,
'module': module
}));
}
if(!_.include(ignores.ignores, module)) {
ignores.ignores.push(module);
this.db.save('ignores', event.rUser.id, ignores, function(err) {
if(!err) {
dbot.instance.ignoreTag(event.user, module);
event.reply(dbot.t('ignored', {
'user': event.user,
'module': module
}));
}
});
} else {
event.reply(dbot.t('already_ignoring', { 'user': event.user }));
}
}.bind(this));
} else {
event.reply(dbot.t('invalid_ignore', { 'user': event.user }));
}
@ -47,139 +76,192 @@ var ignore = function(dbot) {
},
'~unignore': function(event) {
var ignoredModules = [];
if(_.has(dbot.db.ignores, event.user)) {
ignoredModules = dbot.db.ignores[event.user];
}
var module = event.params[1];
if(_.isUndefined(module)) {
event.reply(dbot.t('unignore_usage', {
'user': event.user,
'modules': ignoredModules.join(', ')
}));
} else {
if(_.include(ignoredModules, module)) {
dbot.db.ignores[event.user].splice(dbot.db.ignores[event.user].indexOf(module), 1);
dbot.instance.removeIgnore(event.user, module)
event.reply(dbot.t('unignored', {
'user': event.user,
'module': module
}));
this.api.getUserIgnores(event.rUser, function(err, ignores) {
if(err || !ignores || _.isUndefined(module)) {
if(ignores) {
event.reply(dbot.t('unignore_usage', {
'user': event.user,
'modules': ignores.ignores.join(', ')
}));
} else {
event.reply(dbot.t('empty_unignore_usage', {
'user': event.user
}));
}
} else {
event.reply(dbot.t('invalid_unignore', { 'user': event.user }));
if(_.include(ignores.ignores, module)) {
ignores.ignores = _.without(ignores.ignores, module);
this.db.save('ignores', event.rUser.id, ignores, function(err) {
if(!err) {
dbot.instance.removeIgnore(event.user, module)
event.reply(dbot.t('unignored', {
'user': event.user,
'module': module
}));
}
});
} else {
event.reply(dbot.t('invalid_unignore', { 'user': event.user }));
}
}
}
}.bind(this));
},
'~ban': function(event) {
var user = event.params[1];
var module = event.params[2];
var nick = event.input[1],
item = event.input[2];
if(_.isUndefined(user) || _.isUndefined(module)) {
event.reply(dbot.t('ban_usage', {'user': event.user}));
return;
}
if(module == '*' || _.include(dbot.config.moduleNames, module) || _.include(dbot.commands, module)) {
if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) {
event.reply(dbot.t('already_banned', {
'user': event.user,
'banned': user
}));
return;
}
if(item == '*' || _.include(dbot.config.moduleNames, item) || _.include(dbot.commands, item)) {
dbot.api.users.resolveUser(event.server, nick, function(err, user) {
this.api.getUserIgnores(user, function(err, ignores) {
if(!ignores) {
ignores = {
'id': user.id,
'ignores': [],
'bans': []
};
}
if(_.has(dbot.db.bans, event.params[1])) {
dbot.db.bans[event.params[1]].push(module);
} else {
dbot.db.bans[event.params[1]] = [module];
}
event.reply(dbot.t('banned_success', {
'user': event.user,
'banned': user,
'module': module
}));
if(!_.include(ignores.bans, item)) {
ignores.bans.push(item);
this.db.save('ignores', user.id, ignores, function(err) {
if(!err) {
event.reply(dbot.t('banned_success', {
'user': event.user,
'banned': nick,
'module': item
}));
}
});
} else {
event.reply(dbot.t('already_banned', {
'user': event.user,
'banned': nick
}));
}
}.bind(this));
}.bind(this));
} else {
event.reply(dbot.t('invalid_ban', {'user': event.user}));
event.reply(dbot.t('invalid_ban', { 'user': event.user }));
}
},
'~unban': function(event) {
var bannedModules = [];
var nick = event.input[1],
item = event.input[2];
var user = event.params[1];
var module = event.params[2];
if(_.isUndefined(user) || _.isUndefined(module)) {
event.reply(dbot.t('unban_usage', {'user': event.user}));
} else {
if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) {
dbot.db.bans[user].splice(dbot.db.bans[user].indexOf(module), 1);
event.reply(dbot.t('unbanned_success', {
'user': event.user,
'banned': user,
'module': module
}));
} else {
event.reply(dbot.t('invalid_unban', {
'user': event.user,
'banned': user
}));
}
}
dbot.api.users.resolveUser(event.server, nick, function(err, user) {
this.api.getUserIgnores(user, function(err, ignores) {
if(err || !ignores) {
event.reply(dbot.t('invalid_unban', {
'user': event.user,
'banned': nick
}));
} else {
if(_.include(ignores.bans, item)) {
ignores.bans = _.without(ignores.bans, item);
this.db.save('ignores', user.id, ignores, function(err) {
event.reply(dbot.t('unbanned_success', {
'user': event.user,
'banned': nick,
'module': item
}));
});
} else {
event.reply(dbot.t('invalid_unban', {
'user': event.user,
'banned': nick
}));
}
}
}.bind(this));
}.bind(this));
},
'~ignorechannel': function(event) {
var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]);
var module = event.params[2];
var channelName = event.input[1],
module = event.input[2];
// Ignoring the value of 'ignorable' at the moment
if(module == '*' || _.include(dbot.config.moduleNames, module)) {
if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = [];
if(!_.include(dbot.db.ignores[channel], module)) {
dbot.db.ignores[channel].push(module);
dbot.instance.ignoreTag(channel, module);
event.reply(dbot.t('ignoring_channel', {
'module': module,
'channel': channel
}));
} else {
event.reply(dbot.t('already_ignoring_channel', {
'module': module,
'channel': channel
}));
}
var channel = false;
this.db.search('channel_ignores', {
'server': event.server,
'name': channelName
}, function(result) {
channel = result;
}, function(err) {
if(!channel) {
var id = uuid.v4();
channel = {
'id': id,
'server': event.server,
'name': channelName,
'ignores': []
};
}
if(!_.include(channel.ignores, module)) {
channel.ignores.push(module);
this.db.save('channel_ignores', channel.id, channel, function(err) {
dbot.instance.ignoreTag(channel.name, module);
event.reply(dbot.t('ignoring_channel', {
'module': module,
'channel': channelName
}));
});
} else {
event.reply(dbot.t('already_ignoring_channel', {
'module': module,
'channel': channelName
}));
}
}.bind(this));
} else {
event.reply(dbot.t('module_not_exist', { 'module': module }));
}
},
'~unignorechannel': function(event) {
var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]);
var module = event.params[2];
var channelName = event.input[1],
module = event.input[2],
channel = false;
if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = [];
if(_.include(dbot.db.ignores[channel], module)) {
dbot.db.ignores[channel] = _.without(dbot.db.ignores[channel], module);
dbot.instance.removeIgnore(channel, module);
event.reply(dbot.t('unignoring_channel', {
'module': module,
'channel': channel
}));
} else {
event.reply(dbot.t('not_ignoring_channel', {
'module': module,
'channel': channel
}));
}
this.db.search('channel_ignores', {
'server': event.server,
'name': channelName
}, function(result) {
channel = result;
}, function(err) {
if(channel && _.include(channel.ignores, module)) {
channel.ignores = _.without(channel.ignores, module);
this.db.save('channel_ignores', channel.id, channel, function(err) {
dbot.instance.removeIgnore(channel.name, module);
event.reply(dbot.t('unignoring_channel', {
'module': module,
'channel': channelName
}));
});
} else {
event.reply(dbot.t('not_ignoring_channel', {
'module': module,
'channel': channelName
}));
}
}.bind(this));
}
};
commands['~ban'].access = 'moderator';
commands['~unban'].access = 'moderator';
commands['~ban'].regex = [/^ban ([^ ]+) ([^ ]+)$/, 3];
commands['~unban'].regex = [/^unban ([^ ]+) ([^ ]+)$/, 3];
commands['~ignorechannel'].regex = [/^ignorechannel ([^ ]+) ([^ ]+)$/, 3];
commands['~unignorechannel'].regex = [/^unignorechannel ([^ ]+) ([^ ]+)$/, 3];
commands['~ban'].access = 'power_user';
commands['~unban'].access = 'power_user';
commands['~ignorechannel'].access = 'moderator';
commands['~unignorechannel'].access = 'moderator';
@ -187,12 +269,34 @@ var ignore = function(dbot) {
this.onLoad = function() {
dbot.instance.clearIgnores();
_.each(dbot.db.ignores, function(ignores, item) {
_.each(ignores, function(ignore) {
dbot.instance.ignoreTag(item, ignore);
}, this);
}, this);
};
this.db.scan('ignores', function(ignores) {
dbot.api.users.getUser(ignores.id, function(err, user) {
if(user) {
_.each(ignores.ignores, function(module) {
dbot.instance.ignoreTag(user.currentNick, module);
});
}
});
}, function(err) { });
this.db.scan('channel_ignores', function(channel) {
_.each(channel.ignores, function(module) {
dbot.instance.ignoreTag(channel.name, module);
});
}, function(err) { });
dbot.api.event.addHook('new_current_nick', function(user, oldNick) {
this.api.getUserIgnores(user, function(err, ignores) {
if(ignores) {
_.each(ignores.ignores, function(module) {
dbot.instance.removeIgnore(oldNick, module);
dbot.instance.ignoreTag(user.currentNick, module);
});
}
}.bind(this));
}.bind(this));
}.bind(this);
};
exports.fetch = function(dbot) {

View File

@ -5,7 +5,9 @@
"na'vi": "{user}: Sar: ~ignore ['u]. U, nga ke tìng mikyun: {modules}.",
"cy": "{user}: Defnydd: ~ignore [modiwl]. Modiwlau a allech anwybyddu yw: {modules}.",
"nl": "{user}: Gebruik: ~ignore [module]. Modules die negeert kunnen worden zijn: {modules}.",
"de": "{user}: Benutzung: ~ignore [module]. Module, die ignoriert werden können: {modules}."
"de": "{user}: Benutzung: ~ignore [module]. Module, die ausgeschaltet werden können: {modules}.",
"fr": "{user}: Utilisation: ~ignore [module]. Les modules que vous pouvez ignorer sont: {modules}.",
"it": "{user}: Uso: ~ignore [module]. I moduli che puoi ignorare sono: {modules}."
},
"already_ignoring": {
"en": "{user}: You're already ignoring that module.",
@ -13,7 +15,9 @@
"na'vi": "{user}: 'uri nga ke tìng mikyun srekrr.",
"cy": "{user}: Mi rwyt ti'n anwybyddu'r modiwl yna'n barod.",
"nl": "{user}: Je negeert deze module al.",
"de": "{user}: Dieses Modul wird bereits ignoriert."
"de": "{user}: Dieses Modul ist bereits ausgeschaltet.",
"fr": "{user}: Vous ignorez déjà ce module.",
"it": "{user}: Stai già ignorando questo modulo"
},
"ignored": {
"en": "{user}: Now ignoring {module}.",
@ -21,7 +25,9 @@
"na'vi": "{user}: Nga ke terìng mikyun {module}ne set.",
"cy": "{user}: Nawr yn anwybyddu {module}",
"nl": "{user}: {module} wordt nu genegeerd.",
"de": "{user}: {module} wird nun ignoriert."
"de": "{user}: {module} wird nun ausgeschaltet.",
"fr": "{user}: {module} désormais ignoré.",
"it": "{user}: {module} sarà adesso ignorato"
},
"invalid_ignore": {
"en": "{user}: That isn't a valid module name.",
@ -29,7 +35,9 @@
"na'vi": "{user}: Tsatstxo eyawr ke lu.",
"cy": "{user}: Nid oedd hwna'n modiwl dilys",
"nl": "{user}: Dat is geen geldige modulenaam.",
"de": "{user}: Dies ist nicht der Name eines Moduls."
"de": "{user}: Dies ist kein Name eines Moduls.",
"fr": "{user}: Ceci ne correspond pas à un nom de module valide.",
"it": "{user}: Questo non è un nome di modulo valido"
},
"unignore_usage": {
"en": "{user}: Usage: ~unignore [module]. Modules you are currently ignoring: {modules}.",
@ -37,7 +45,19 @@
"na'vi": "{user}: Sar: ~unignore ['u]. Uri, nga ke terìng mikyun: {modules}.",
"cy": "{user}: Defnydd: ~unignore [modiwl]. Modiwlau rydech yn anwybyddu ar hyn o bryd: {modules}",
"nl": "{user}: Gebruik: ~unignore [module]. Modules die momenteel worden genegeerd: {modules}.",
"de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ignoriert werden: {modules}."
"de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ausgeschaltet sind: {modules}.",
"fr": "{user}: Utilisation: ~unignore [module]. Modules que vous ignorez actuellement: {modules}.",
"it": "{user}: Uso: ~unignore [module]. Module che ignori attualmente: {modules}."
},
"empty_unignore_usage": {
"en": "{user}: Usage: ~unignore [module].",
"es": "{user}: Modo de empleo: ~unignore [módulo].",
"na'vi": "{user}: Sar: ~unignore ['u].",
"cy": "{user}: Defnydd: ~unignore [modiwl].",
"nl": "{user}: Gebruik: ~unignore [module].",
"de": "{user}: Benutzung: ~unignore [module].",
"fr": "{user}: Utilisation: ~unignore [module].",
"it": "{user}: Uso: ~unignore [module]."
},
"invalid_unignore": {
"en": "{user}: You're not ignoring that module or it doesn't exist.",
@ -45,7 +65,9 @@
"na'vi":"{user}: Nga terìng mikyun fu fì'ul fìtsengit ke tok.",
"cy": "{user}: Nid wyt ti'n anwybyddu'r modiwl yna neu nid yw e'n bodoli",
"nl": "{user}: Deze module bestaat niet of wordt niet genegeerd.",
"de": "{user}: Dieses Modul wird entweder nicht ignoriert oder existiert nicht."
"de": "{user}: Dieses Modul ist entweder ausgeschaltet oder existiert nicht.",
"fr": "{user}: Vous n'ignorez pas ce module ou il n'existe pas.",
"it": "{user}: Non stai ignorando questo modulo o non esiste."
},
"unignored": {
"en": "{user}: No longer ignoring {module}.",
@ -53,83 +75,109 @@
"na'vi": "{user}: Nga terìng mikyun {module}ne set",
"cy": "{user}: Ddim yn anwybyddu {module} bellach",
"nl": "{user}: {module} wordt niet langer genegeerd.",
"de": "{user}: {module} wird nicht länger ignoriert."
"de": "{user}: {module} ist nicht länger ausgeschaltet.",
"fr": "{user}: {module} n'est plus ignoré à présent.",
"it": "{user}: {module} non viene attualmente più ignorato"
},
"ban_usage": {
"en": "{user}: Usage: ~ban [user] [module/command]. Use * for all modules and commands.",
"cy": "{user}: Defnydd: ~ban [defnyddiwr] [modiwl/gorchymyn]. Defnyddio * am pob modiwlau a gorchmynion.",
"nl": "{user}: Gebruik: ~ban [gebruiker] [module/commando]. Gebruik * voor alle modules en alle commandos.",
"de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle."
"de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle.",
"fr": "{user}: Utilisation: ~ban [user] [module/command]. Utilisez * pour tous les modules et commandes.",
"it": "{user}: Uso: ~ban [user] [module/command]. Utilizza * per tutti i moduli e commandi."
},
"already_banned": {
"en": "{user}: {banned} is already banned from that module.",
"cy": "{user}: {banned} eisoes wedi ei wahardd o'r modiwl.",
"nl": "{user}: {banned} is al geband van deze module.",
"de": "{user}: {banned} ist bereits von diesem Modul gebannt."
"de": "{user}: {banned} ist bereits von diesem Modul gebannt.",
"fr": "{user}: {banned} est déjà interdit d'utiliser ce module.",
"it": "{user}: {banned} è già bandito da usare questo modulo."
},
"banned_success": {
"en": "{user}: {banned} is now banned from {module}.",
"cy": "{user}: {banned} ei wahardd yn awr am {module}.",
"nl": "{user}: {banned} mag {module} nu niet meer gebruiken.",
"de": "{user}: {banned} ist nun von {module} gebannt."
"de": "{user}: {banned} ist nun von {module} gebannt.",
"fr": "{user}: {banned} est maintenant interdit d'utiliser {module}.",
"it": "{user}: {banned} è stato adesso bandito da usare {module}."
},
"invalid_ban": {
"en": "{user}: That isn't a valid module name.",
"cy": "{user}: Nid oedd hwna'n modiwl dilys",
"nl": "{user}: Dat is geen geldige modulenaam.",
"de": "{user}: Dies ist nicht der Name eines Moduls."
"de": "{user}: Dies ist kein Name eines Moduls.",
"fr": "{user}: Ceci n'est pas un nom de module valide.",
"it": "{user}: Queso non è il nome di un modulo valido."
},
"unban_usage": {
"en": "{user}: Usage: ~unban [user] [module].",
"cy": "{user}: Defnydd: ~unban [defnyddiwr] [modiwl].",
"nl": "{user}: Gebruik: ~unban [gebruiker] [module].",
"de": "{user}: Benutzung: ~unban [Benutzer] [module]."
"de": "{user}: Benutzung: ~unban [Benutzer] [module].",
"fr": "{user}: Utilisation: ~unban [user] [module].",
"it": "{user}: Uso: ~unban [user] [module]."
},
"invalid_unban": {
"en": "{user}: {banned} is not banned from that module or it doesn't exist.",
"cy": "{user}: Nid oedd {banned} wedi ei wahardd o'r modiwl, neu nid yw'n bodoli.",
"nl": "{user}: {banned} is niet geband van die module of de module bestaat niet.",
"de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht."
"de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht.",
"fr": "{user}: {banned} n'est pas interdit d'utiliser ce module, ou il n'existe pas.",
"it": "{user}: {banned} non è stato bandito da questo modulo o non esiste."
},
"unbanned_success": {
"en": "{user}: {banned} is no longer banned from {module}.",
"cy": "{user}: Nid yw {banned} yn cael ei wahardd mwyach.",
"nl": "{user}: {banned} mag {module} weer gebruiken.",
"de": "{user}: {banned} wurde von {module} entbannt."
"de": "{user}: {banned} wurde von {module} entbannt.",
"fr": "{user}: {banned} n'est plus interdit d'utiliser {module}.",
"it": "{user}: {banned} non è più bandito dall' utilizzare {module}."
},
"ignoring_channel": {
"en": "Now ignoring {module} in {channel}.",
"na'vi": "Oe ke stayawm {module}ur mì {channel}",
"cy": "Bellach yn anwybyddu {module} yn {channel}.",
"nl": "{module} wordt nu genegeerd in {channel}.",
"de": "{module} in [channel} wird nun ignoriert."
"de": "{module} in {channel} ist nun ausgeschaltet.",
"fr": "{module} dans {channel} maintenant ignoré.",
"it": "{module} in {channel} viene adesso ignorato."
},
"already_ignoring_channel": {
"en": "Already ignoring {module} in {channel}.",
"na'vi": "Oe ke stayawm {module}ur mì {channel} li",
"cy": "Eisoes anwybyddu {module} yn {channel}",
"nl": "{module} wordt al genegeerd in {channel}.",
"de": "{module} in {channel} wird bereits ignoriert."
"de": "{module} in {channel} ist bereits ausgeschaltet.",
"fr": "{module} dans {channel} déjà ignoré.",
"it": "{module} in {channel} già ignorato."
},
"module_not_exist": {
"en": "{module} isn't loaded or doesn't exist.",
"na'vi": "Oel ke omum teri {module}it fu {module} ke fkeytok",
"cy": "Dydy {module} ddim yn lwythodd, neu ddim yn bodoli.",
"nl": "{module} is niet geladen of bestaat niet.",
"de": "{module} ist nicht geladen oder existiert nicht."
"de": "{module} ist nicht geladen oder existiert nicht.",
"fr": "{module} n'est pas chargé ou n'existe pas.",
"it": "{module} non caricato o non esiste"
},
"unignoring_channel": {
"en": "No longer ignoring {module} in {channel}.",
"na'vi": "Oel stayawm {module}ur mì {channel} set.",
"cy": "Nid anwybyddu {module} yn {channel} mwyach.",
"nl": "{module} wordt niet meer genegeerd in {channel}.",
"de": "{module} in {channel} wird nicht länger ignoriert."
"de": "{module} in {channel} ist nicht länger ausgeschaltet.",
"fr": "{module} dans {channel} n'est plus ignoré à présent.",
"it": "{module} in {channel} non viene più ignorato."
},
"not_ignoring_channel": {
"en": "{module} wasn't being ignored in {channel}.",
"na'vi": "Oel stayawm {module}ur mì {channel} li.",
"cy": "Nid yw {module} yn cael ei anwybyddu yn {channel}.",
"nl": "{module} werd niet genegeerd in {channel}.",
"de": "{module} wurde in {channel} nicht ignoriert."
"de": "{module} war in {channel} nicht ausgeschaltet.",
"fr": "{module} n'était pas ignoré dans {channel}.",
"it": "{module} non veniva ignorato in {channel}"
}
}

View File

@ -1,7 +1,8 @@
{
"dbKeys": [ "imgur" ],
"dependencies": [ "web", "api" ],
"dependencies": [ "web", "api", "link" ],
"imagelength": 5,
"ricachelength": 7,
"nsfwwarn": true,
"apikey": "86fd3a8da348b65",
"highscore": "ricount",

View File

@ -5,14 +5,29 @@
var _ = require('underscore')._,
request = require('request'),
crypto = require('crypto');
async = require('async'),
crypto = require('crypto'),
humanise = require('humanize');
var imgur = function(dbot) {
this.db = dbot.db.imgur;
this.ApiRoot = 'https://api.imgur.com/3/';
this.ExcludeRes = [
{ 'w': 800, 'h': 600 },
{ 'w': 1024, 'h': 768 },
{ 'w': 1280, 'h': 768 },
{ 'w': 1280, 'h': 960 },
{ 'w': 1366, 'h': 768 },
{ 'w': 1600, 'h': 900 },
{ 'w': 1680, 'h': 1050 },
{ 'w': 1920, 'h': 1080 },
{ 'w': 1024, 'h': 640 }
];
this.riCache = [];
this.internalAPI = {
'infoString': function(imgData) {
info = '';
if(imgData && _.has(imgData, 'data') && !_.isUndefined(imgData.data.type)) {
if(!_.isUndefined(imgData) && _.has(imgData, 'data') && !_.isUndefined(imgData.data.type)) {
imgData = imgData.data;
if(imgData.title) {
info += imgData.title + ' - ';
@ -28,6 +43,8 @@ var imgur = function(dbot) {
}
info += imgData.views + ' views (';
info += imgData.width + 'x' + imgData.height + ')';
info += ' ('+humanise.filesize(imgData.size)+')';
}
return info;
@ -35,13 +52,13 @@ var imgur = function(dbot) {
'albumInfoString': function(albumData) {
var info = '';
if(albumData && _.has(albumData, 'data') && !_.isUndefined(albumData.data.id)) {
if(!_.isUndefined(albumData) && _.has(albumData, 'data') && !_.isUndefined(albumData.data.id)) {
albumData = albumData.data;
if(albumData.title) {
info += albumData.title + ' - ';
}
if(albumData.description) {
info += albumData.description + ' is ';
info += albumData.description.split('\n')[0] + ' is ';
}
info += 'an album with ' + albumData.images_count + ' images ';
info += 'and ' + albumData.views + ' views';
@ -54,7 +71,7 @@ var imgur = function(dbot) {
'galleryInfoString': function(galData) {
var info = '';
if(galData && _.has(galData, 'data') && !_.isUndefined(galData.data.is_album)) {
if(!_.isUndefined(galData) && _.has(galData, 'data') && !_.isUndefined(galData.data.is_album)) {
if(galData.data.is_album === true) {
info = this.internalAPI.albumInfoString(galData);
} else {
@ -76,30 +93,52 @@ var imgur = function(dbot) {
var testSlug = random(5);
var testUrl = 'http://i.imgur.com/' +
testSlug +
'.' + ext[_.random(0, ext.length - 1)];
this.db.totalHttpRequests += 1;
var image = request(testUrl, function(error, response, body) {
'.' + ext[_.random(0, ext.length - 1)],
fbman = false;
dbot.db.imgur.totalHttpRequests += 1;
request(testUrl, function(error, response, body) {
// 492 is body.length of a removed image
if(!error && response.statusCode == 200 && body.length != 492) {
this.db.totalImages += 1;
dbot.db.imgur.totalImages += 1;
var hash = crypto.createHash('md5').update(body).digest("hex");
if(_.has(dbot.modules, 'quotes')){
// autoadd: {"abcdef": "facebookman"}
if(_.has(dbot.config.imgur.autoadd,hash)){
var category = dbot.config.imgur.autoadd[hash];
if(_.has(dbot.config.modules.imgur.autoadd,hash)){
fbman = true;
var category = this.config.autoadd[hash];
if (_.contains(category, testUrl)){
// there's probably less than 62^5 chance of this happening
} else {
if(!_.has(dbot.db.quoteArrs, category)) dbot.db.quoteArrs[category] = [];
dbot.db.quoteArrs[category].push(testUrl);
dbot.api.quotes.addQuote(category, testUrl,
dbot.config.name, function() { });
}
}
}
callback(testUrl, testSlug,hash);
callback(testUrl, testSlug, hash, fbman);
} else {
this.api.getRandomImage(callback);
}
}.bind(this));
}.bind(this));
},
'getGoodRandomImage': function(callback) {
this.api.getRandomImage(function(url, slug, hash, fbman) {
this.api.getImageInfo(slug, function(imgData) {
if(!_.isUndefined(imgData) &&
imgData.data &&
imgData.data.height > 500 && imgData.data.width > 500 &&
!_.any(this.ExcludeRes, function(res) {
return imgData.data.height == res.h && imgData.data.width == res.w;
})) {
callback(url, imgData);
} else if(fbman === true) {
callback(url, imgData);
} else {
this.api.getGoodRandomImage(callback);
}
}.bind(this));
}.bind(this));
},
'getImageInfoString': function(slug, callback) {
@ -113,10 +152,10 @@ var imgur = function(dbot) {
'url': 'https://api.imgur.com/3/image/' + slug + '.json',
'json': true,
'headers': {
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
'Authorization': 'Client-ID ' + this.config.apikey
}
}, function(err, response, body) {
this.db.totalApiRequests += 1;
dbot.db.imgur.totalApiRequests += 1;
callback(body);
}.bind(this));
},
@ -126,7 +165,7 @@ var imgur = function(dbot) {
'url': 'https://api.imgur.com/3/album/' + slug + '.json',
'json': true,
'headers': {
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
'Authorization': 'Client-ID ' + this.config.apikey
}
}, function(err, response, body) {
this.db.totalApiRequests += 1;
@ -139,7 +178,7 @@ var imgur = function(dbot) {
'url': 'https://api.imgur.com/3/gallery/' + slug + '.json',
'json': true,
'headers': {
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
'Authorization': 'Client-ID ' + this.config.apikey
}
}, function(err, response, body) {
this.db.totalApiRequests += 1;
@ -154,17 +193,95 @@ var imgur = function(dbot) {
this.commands = {
'~ri': function(event) {
var local = event.user;
if(event.params[1]) {
local = event.params.splice(1, event.params.length - 1).join(' ').trim();
}
var postImage = function(link, imgData) {
var info = this.internalAPI.infoString(imgData);
event.reply('['+this.config.outputPrefix + '] ' + local + ': ' + link + ' [' + info + ']');
}.bind(this);
var newCacheImage = function(link, imgData) {
this.riCache.push([link, imgData]);
}.bind(this);
var callback = postImage;
if(this.riCache.length > 0) {
var image = this.riCache.pop();
postImage(image[0], image[1]);
callback = newCacheImage;
}
this.api.getGoodRandomImage(callback);
},
// Legacy RI
'~lri': function(event) {
var local = event.user;
if(event.params[1]) {
local = event.params.splice(1, event.params.length - 1).join(' ').trim();
}
this.api.getRandomImage(function(link, slug) {
this.api.getImageInfo(slug, function(imgData) {
var info = this.internalAPI.infoString(imgData);
event.reply(event.user + ': ' + link + ' [' + info + ']');
event.reply('['+this.config.outputPrefix + '] ' + local + ': ' + link + ' [' + info + ']');
}.bind(this));
}.bind(this));
},
// Super RI
'~sri': function(event) {
var local = event.user;
if(event.params[1]) {
local = event.params.splice(1, event.params.length - 1).join(' ').trim();
}
request.get({
'url': this.ApiRoot + 'gallery/random/random/',
'json': true,
'headers': {
'Authorization': 'Client-ID ' + this.config.apikey
}
}, function(err, response, body) {
if(!_.isUndefined(body) && body.data && body.data[0] != undefined) {
var num = _.random(0, body.data.length - 1);
this.api.getGalleryInfo(body.data[num].id, function(gal) {
event.reply('['+this.config.outputPrefix + '] ' + local + ': ' + gal.data.link + ' [' +
this.internalAPI.galleryInfoString(gal) + ']');
}.bind(this));
}
}.bind(this));
},
'~imgur': function(event) {
var term = event.input[1];
request.get({
'url': this.ApiRoot + 'gallery/search/',
'json': true,
'headers': {
'Authorization': 'Client-ID ' + this.config.apikey
},
'qs': {
'q': term
}
}, function(err, response, body) {
if(!_.isUndefined(body) && body.data && body.data[0] != undefined) {
var num = _.random(0, body.data.length - 1);
this.api.getGalleryInfo(body.data[num].id, function(gal) {
event.reply(dbot.t('imgurinfo', {
'info': this.internalAPI.galleryInfoString(gal)
}) + ' - ' + gal.data.link);
}.bind(this));
} else {
event.reply(dbot.t('imgur_noresults'));
}
}.bind(this));
}
}
this.commands['~imgur'].regex = [/^imgur ([\d\w\s-]*)/, 2];
this.onLoad = function() {
var imgurHandler = function(event, matches, name) {
var imgurHandler = function(matches, name, callback) {
if(matches[1]) {
var dataCallback = function(data) {
var info;
@ -176,7 +293,7 @@ var imgur = function(dbot) {
info = this.internalAPI.galleryInfoString(data);
}
if(info) event.reply(dbot.t('imgurinfo', { 'info': info }));
if(info) callback(dbot.t('imgurinfo', { 'info': info }));
}.bind(this);
if(name == 'imgurimage') {
@ -194,9 +311,17 @@ var imgur = function(dbot) {
dbot.api.link.addHandler('imgurimage', /https?:\/\/i\.imgur\.com\/([a-zA-Z0-9]+)\.([jpg|png|gif])/, imgurHandler);
dbot.api.link.addHandler('imgurimage', /https?:\/\/imgur\.com\/([a-zA-Z0-9]+)/, imgurHandler);
async.times(this.config.ricachelength, function(n, next) {
this.api.getGoodRandomImage(function(link, imgData) {
this.riCache.push([ link, imgData ]);
next();
}.bind(this));
}.bind(this), function() {});
if(!_.has(dbot.db.imgur, 'totalHttpRequests')) dbot.db.imgur.totalHttpRequests = 0;
if(!_.has(dbot.db.imgur, 'totalApiRequests')) dbot.db.imgur.totalApiRequests = 0;
if(!_.has(dbot.db.imgur, 'totalImages')) dbot.db.imgur.totalImages = 0;
this.db = dbot.db.imgur;
}.bind(this);
};

View File

@ -3,13 +3,7 @@ var _ = require('underscore')._;
var pages = function(dbot) {
return {
'/imgur/random': function(req, res) {
var quoteCat = dbot.db.quoteArrs[dbot.config.imgur.highscore],
highScore = 0;
if(quoteCat) {
highScore = _.last(quoteCat);
}
var highScore = 0;
res.render('imgurr', { "highscore" : highScore });
},

View File

@ -4,9 +4,19 @@
"na'vi": "kxawm ke wivìntxu evengur",
"cy": "Gallai fod yn anniogel ar gwaith",
"nl": "bevat mogelijk gevoelige beelden",
"de": "Könnte 18+ Material enthalten"
"de": "Könnte 18+ Material enthalten",
"fr": "peut être risqué pour le travail (NSFW)",
"it": "può essere rischioso al lavoro (NSFW)"
},
"imgurinfo": {
"en": "[{info}]"
"en": "[{info}]",
"de": "[{info}]",
"fr": "[{info}]",
"it": "[{info}]"
},
"imgur_noresults": {
"en": "No results found.",
"de": "Kein Suchergebnis.",
"it": "Nessun risultato"
}
}

View File

@ -5,6 +5,5 @@
}
},
"dependencies": [ "command" ],
"ignorable": true,
"help": "http://github.com/reality/depressionbot/blob/master/modules/js/README.md"
"ignorable": true
}

View File

@ -4,31 +4,38 @@
* the channel. Also allows admins to run un-sandboxed Javascript code with
* access to the DepressionBot instance memory.
*/
var vm = require('vm');
var sbox = require('sandbox');
var VM = require('vm2').VM;
var js = function(dbot) {
var commands = {
// Run JS code sandboxed, return result to channel.
'~js': function(event) {
try {
var s = new sbox();
s.run(event.input[1], function(output) {
event.reply(output.result);
}.bind(this));
} catch(err) {}
var s = new VM({timeout: 1000, sandbox: {}});
event.reply(s.run(event.input[1]));
} catch(err) { event.reply(err); }
},
// Run JS code un-sandboxed, with access to DBot memory (admin-only).
'~ajs': function(event) {
var callback = function() {
var args = Array.prototype.slice.call(arguments);
for(var i=0;i<args.length;i++) {
var arg = args[i];
if(_.isObject(arg) && !_.isArray(arg)) {
arg = '[object Object]: ' + _.keys(arg).join(', ');
}
event.reply('Callback[' + i + ']: ' + arg);
}
};
var ret = eval(event.input[1]);
if(ret !== undefined) {
event.reply(ret);
}
}
};
commands['~js'].regex = [/^~js (.*)/, 2];
commands['~ajs'].regex = [/^~ajs (.*)/, 2];
commands['~js'].regex = [/^js (.*)/, 2];
commands['~ajs'].regex = [/^ajs (.*)/, 2];
commands['~ajs'].access = 'admin';
this.name = 'js';

View File

@ -0,0 +1,5 @@
{
"announce": [ { "server": "tripsit", "name": "#dbot" } ],
"dbKeys": [ "karma" ],
"dbType": "redis"
}

201
modules/karma/karma.js Normal file
View File

@ -0,0 +1,201 @@
/**
* Module Name: Karma
* Description: Thanking, with Karma!
*/
var _ = require('underscore')._;
var karma = function(dbot) {
this.lastKarma = {};
this.internalAPI = {
'getKarma': function(item, callback) {
this.db.read('karma', item.toLowerCase(), callback);
}.bind(this),
'setKarma': function(item, value, callback) {
this.db.save('karma', item.toLowerCase(), {
'item': item.toLowerCase(),
'karma': value
}, callback);
}.bind(this)
};
this.commands = {
'karma': function(event) {
var item = event.params[1] || event.user;
this.internalAPI.getKarma(item, function(err, karma) {
if(!err && karma) {
karma = karma.karma;
} else {
karma = 0;
}
event.reply(dbot.t('karma', {
'item': item,
'karma': karma
}));
});
},
'setkarma': function(event) {
var item = event.params[1],
value = parseInt(event.params[2]);
this.internalAPI.setKarma(item, value, function(err, karma) {
event.reply(dbot.t('newkarma', {
'item': item,
'value': value
}));
});
},
'unkarmaiest': function(event) {
var karmas = {};
this.db.scan('karma', function(karma) {
if(karma && !_.isUndefined(karma.item)) {
karmas[karma.item] = karma.karma;
}
}.bind(this), function(err) {
var qSizes = _.chain(karmas)
.pairs()
.sortBy(function(category) { return category[1]; })
.first(10)
.value();
var qString = 'Unkarmaiest: ';
for(var i=0;i<qSizes.length;i++) {
qString += qSizes[i][0] + " (" + qSizes[i][1] + "), ";
}
event.reply(qString.slice(0, -2));
});
},
'karmaiest': function(event) {
var karmas = {};
this.db.scan('karma', function(karma) {
if(karma && !_.isUndefined(karma.item)) {
karmas[karma.item] = karma.karma;
}
}.bind(this), function(err) {
var qSizes = _.chain(karmas)
.pairs()
.sortBy(function(category) { return category[1]; })
.reverse()
.first(10)
.value();
var qString = 'Karmaiest: ';
for(var i=0;i<qSizes.length;i++) {
qString += qSizes[i][0] + " (" + qSizes[i][1] + "), ";
}
event.reply(qString.slice(0, -2));
});
},
'wattest': function(event) {
var karmas = {};
this.db.scan('karma', function(karma) {
if(karma && !_.isUndefined(karma.item)) {
if(karma.item.match(/_wat$/)) {
karmas[karma.item] = karma.karma;
}
}
}.bind(this), function(err) {
var qSizes = _.chain(karmas)
.pairs()
.sortBy(function(category) { return category[1]; })
.reverse()
.first(10)
.value();
var qString = 'Karmaiest: ';
for(var i=0;i<qSizes.length;i++) {
qString += qSizes[i][0] + " (" + qSizes[i][1] + "), ";
}
event.reply(qString.slice(0, -2));
});
}
};
this.commands.setkarma.access = 'admin';
this.listener = function(event) {
dbot.api.ignore.isUserBanned(event.rUser, 'karma', function(isBanned) {
if(!isBanned) {
var match = event.message.match(/^(.+)(\+\+|\-\-)$/);
if(event.user !== dbot.config.name && match && match[1].length < 25) {
match[1] = match[1].replace(/(\+|\-)/g,'').replace(/:/g,'').trim();
var timeout = 5000;
/* if(event.channel.name == '#stims' || event.channel.name == '##meth' || event.channel.name == '##sweden') {
timeout = 20000;
}*/
if(_.has(this.lastKarma, event.rUser.id) && this.lastKarma[event.rUser.id]+ timeout > Date.now()) {
return event.reply('Try again in a few seconds : - )');
} else if(event.rUser.currentNick.toLowerCase() === match[1].toLowerCase() || event.rUser.primaryNick.toLowerCase() === match[1].toLowerCase()) {
return event.reply('Stop playing with yourself : - )');
} else if(event.channel == event.user) {
return event.reply('Don\'t be a Secretive Sally : - )');
}
if(event.channel.name == '##wat') {
match[1] = match[1].replace(/_wat$/, '');
match[1] += '_wat';
}
this.internalAPI.getKarma(match[1], function(err, karma) {
if(!karma) {
karma = 0;
} else {
karma = karma.karma;
}
if(match[2] === '--') {
if(match[1].toLowerCase() =='weed') {
karma -= 2;
} else {
karma -= 1;
}
} else {
if(match[1].toLowerCase() == 'weed') {
karma += 2;
} else {
karma += 1;
}
}
this.internalAPI.setKarma(match[1], karma, function(err, karma) {
this.lastKarma[event.rUser.id] = Date.now();
var pre;
if(karma.karma > 0) {
pre = '[\u00039karma\u000f]';
karma.karma = '\u00039 '+karma.karma+'\u000f';
} else if(karma.karma < 0) {
pre = '[\u00034karma\u000f]';
karma.karma = '\u00034 '+karma.karma+'\u000f';
} else {
pre = '[\u00036karma\u000f]';
karma.karma = '\u00036 '+karma.karma+'\u000f';
}
event.reply(pre + ' ' + dbot.t('newkarma', {
'item': match[1],
'value': karma.karma
}));
if(_.has(dbot.modules, 'log')) {
dbot.api.log.logWithChannel(event.server, event.channel, event.rUser.primaryNick, event.message);
}
}.bind(this));
}.bind(this));
}
}
}.bind(this));
}.bind(this);
this.on = 'PRIVMSG';
};
exports.fetch = function(dbot) {
return new karma(dbot);
};

View File

@ -0,0 +1,8 @@
{
"karma": {
"en": "[karma] {item} has {karma} karma"
},
"newkarma": {
"en": "{item} now has{value} karma"
}
}

View File

@ -1,278 +1,512 @@
var _ = require('underscore')._;
var _ = require('underscore')._,
uuid = require('node-uuid');
var commands = function(dbot) {
var commands = {
/*** Kick Management ***/
'~quiet': function(event) {
var server = event.server,
quieter = event.user,
minutes = event.input[1],
channel = event.input[2],
quietee = event.input[3].trim();
var commands = function (dbot) {
var commands = {
/*** Kick Management ***/
'~quiet': function (event) {
var server = event.server,
quieter = event.rUser,
duration = event.input[1],
channel = (event.input[2] || event.channel.name).trim(),
quietee = event.input[3].trim(),
reason = event.input[4] || "N/A";
if(_.isUndefined(channel)) {
channel = event.channel.name;
this.api.quietUser(server, quieter, duration, channel, quietee, reason, function (response) {
event.reply(response);
});
},
'~timeout': function (event) {
var server = event.server,
quieter = event.rUser,
duration = this.config.timeoutTime,
channel = event.channel.name,
quietee = event.input[1],
reason = event.input[2] || "N/A";
reason += ' #timeout';
dbot.api.users.resolveUser(server, quietee, function (err, user) {
if (!err && user) {
if (!_.has(this.recentTimeouts, user.id)) {
this.recentTimeouts[user.id] = 0;
}
this.recentTimeouts[user.id] += 1;
setTimeout(function () {
this.recentTimeouts[user.id] -= 1;
if (this.recentTimeouts[user.id] == 0) {
delete this.recentTimeouts[user.id];
}
channel = channel.trim();
}
.bind(this), 3600000);
if(!_.isUndefined(minutes)) {
minutes = parseFloat(minutes.trim());
var msTimeout = new Date(new Date().getTime() + (minutes * 60000));
dbot.api.timers.addTimeout(msTimeout, function() {
this.api.unquiet(server, quietee, channel);
}.bind(this));
event.reply(dbot.t('tquieted', {
'quietee': quietee,
'minutes': minutes
}));
if (this.recentTimeouts[user.id] == 3) {
duration = null;
reason += ' #permatimeout';
dbot.say(event.server, dbot.config.servers[event.server].admin_channel, quietee + ' has been given three timeouts in the last hour, and so has been quieted indefinitely in ' + channel + '. Please review.');
}
this.api.quietUser(server, quieter, duration, channel, quietee, reason, function (response) {
event.reply(response);
});
}
}
.bind(this));
},
'~unquiet': function (event) {
var server = event.server,
quieter = event.user,
channel = (event.input[1] || event.channel.name).trim(),
quietee = event.input[2].trim();
if (_.has(this.hosts[server], quietee)) {
if (_.include(this.config.quietBans, channel)) {
this.api.unban(server, this.hosts[server][quietee], channel);
} else {
this.api.unquiet(server, this.hosts[server][quietee], channel);
}
event.reply(dbot.t('unquieted', {
'quietee': quietee
}));
dbot.api.report.notify('unquiet', server, event.rUser, channel,
dbot.t('unquiet_notify', {
'unquieter': quieter,
'quietee': quietee
}), false, quietee);
}
},
'~ckick': function (event) {
var server = event.server,
kicker = event.user,
kickee = event.input[2],
channel = event.input[1],
reason = event.input[3];
if (_.isUndefined(channel)) {
channel = event.channel.name;
}
channel = channel.trim();
this.api.kick(server, kickee, channel, reason + ' (requested by ' + kicker + ')');
dbot.api.report.notify('kick', server, event.rUser, channel, dbot.t('ckicked', {
'kicker': kicker,
'kickee': kickee,
'reason': reason
}), false, kickee);
},
// Kick and ban from all channels on the network.
'~nban': function (event) {
if (!event.input)
return;
var server = event.server,
banner = event.user,
timeout = event.input[1],
banee = event.input[2],
reason = event.input[3],
adminChannel = dbot.config.servers[server].admin_channel,
channels = _.keys(dbot.instance.connections[server].channels),
network = event.server;
if (this.config.network_name[event.server]) {
network = this.config.network_name[event.server];
}
dbot.api.nickserv.getUserHost(event.server, banee, function (host) {
// Add host record entry
if (host) {
var didKill = false;
if ((reason.match('#line') || reason.match('#specialk') || reason.match('#kline')) && _.include(dbot.access.moderator(), event.rUser.primaryNick)) {
didKill = true;
var t = ' !P ';
if (timeout) {
t = ' !T ' + timeout + ' ';
}
dbot.say(event.server, 'operserv', 'akill add ' + banee + t + banee + ' banned by ' + banner + ': ' + reason);
}
// Do not ban if user was killed - redundant
if(!didKill) {
// Ban from current channel first
this.api.ban(server, host, event.channel);
this.api.kick(server, banee, event.channel, reason +
' (network-wide ban)');
channels = _.without(channels, event.channel);
if (!_.isUndefined(adminChannel)) {
channels = _.without(channels, adminChannel);
} else {
event.reply(dbot.t('quieted', { 'quietee': quietee }));
adminChannel = event.channel.name;
}
this.api.quiet(server, quietee, channel);
},
'~unquiet': function(event) {
var server = event.server,
quieter = event.user,
channel = event.input[1],
quietee = event.input[2].trim();
if(_.isUndefined(channel)) {
channel = event.channel.name;
// Ban the user from all channels
var i = 0;
var banChannel = function (channels) {
if (i >= channels.length)
return;
var channel = channels[i];
this.api.ban(server, host, channel);
this.api.kick(server, banee, channel, reason +
' (network-wide ban)');
i++;
banChannel(channels);
}
channel = channel.trim();
.bind(this);
banChannel(channels);
}
this.api.unquiet(server, quietee, channel);
event.reply(dbot.t('unquieted', { 'quietee': quietee }));
},
this.hosts[event.server][banee] = host;
'~ckick': function(event) {
var server = event.server,
kicker = event.user,
kickee = event.input[2],
channel = event.input[1],
reason = event.input[3];
// Create notify string
if (!_.isUndefined(timeout)) {
timeout = timeout.trim();
this.api.kick(server, kickee, channel, reason + ' (requested by ' + kicker + ')');
var msTimeout = new Date(new Date().getTime() + (parseFloat(timeout) * 3600000));
if (_.has(dbot.modules, 'remind')) {
msTimeout = dbot.api.remind.parseTime(timeout);
if (!msTimeout) {
return event.reply('Invalid time. Remember you must give e.g. 5m now.');
}
timeout = timeout.replace(/([\d]+)d/, '$1 days').replace(/([\d]+)h/, '$1 hours ').replace(/([\d]+)m/, '$1 minutes ').replace(/([\d]+)s/, '$1 seconds').trim();
} else {
timeout += ' hours';
}
dbot.api.report.notify(server, channel, dbot.t('ckicked', {
'kicker': kicker,
'kickee': kickee,
'channel': channel,
'reason': reason
}));
},
// Do not schedule unbans if the user was killed as no ban was put in place
if(!didKill) {
if (!_.has(this.tempBans, event.server))
this.tempBans[event.server] = {};
this.tempBans[event.server][banee] = msTimeout;
this.internalAPI.addTempBan(event.server, banee, msTimeout);
}
'~cban': function(event) {
var server = event.server,
banner = event.user,
banee = event.input[2],
channel = event.input[1],
reason = event.input[3];
this.api.ban(server, banee, channel);
this.api.kick(server, kickee, channel, reason + ' (requested by ' + banner + ')');
dbot.api.report.notify(server, channel, dbot.t('cbanned', {
var notifyString = dbot.t('tbanned', {
'network': network,
'banner': banner,
'banee': banee,
'channel': channel,
'hours': timeout,
'host': host,
'reason': reason
}));
},
});
} else {
var notifyString = dbot.t('nbanned', {
'network': network,
'banner': banner,
'banee': banee,
'host': host,
'reason': reason
});
}
// Kick and ban from all channels on the network.
'~nban': function(event) {
if(!event.input) return;
var server = event.server,
banner = event.user,
timeout = event.input[1],
banee = event.input[2],
reason = event.input[3],
adminChannel = this.config.admin_channel[event.server];
channels = dbot.config.servers[server].channels,
network = event.server;
if(this.config.network_name[event.server]) {
network = this.config.network_name[event.server];
}
console.log(timeout);
console.log(banee);
console.log(reason);
dbot.api.nickserv.getUserHost(event.server, banee, function(host) {
// Add host record entry
if(host) {
if(!_.has(this.hosts, event.server)) this.hosts[event.server] = {};
this.hosts[event.server][banee] = host;
// Create notify string
if(!_.isUndefined(timeout)) {
timeout = parseFloat(timeout.trim());
var msTimeout = new Date(new Date().getTime() + (timeout * 3600000));
if(!_.has(this.tempBans, event.server)) this.tempBans[event.server] = {};
this.tempBans[event.server][banee] = msTimeout;
this.internalAPI.addTempBan(event.server, banee, msTimeout);
var notifyString = dbot.t('tbanned', {
'network': network,
'banner': banner,
'banee': banee,
'hours': timeout,
'reason': reason
});
var quoteString = dbot.t('tban_quote', {
'banee': banee,
'banner': banner,
'hours': timeout,
'time': new Date().toUTCString(),
'reason': reason
});
} else {
var notifyString = dbot.t('nbanned', {
'network': network,
'banner': banner,
'banee': banee,
'reason': reason
});
var quoteString = dbot.t('nban_quote', {
'banee': banee,
'banner': banner,
'time': new Date().toUTCString(),
'reason': reason
});
}
// Add qutoe category documenting ban
if(this.config.document_bans && _.has(dbot.modules, 'quotes')) {
dbot.db.quoteArrs['ban_' + banee.toLowerCase()] = [ quoteString ];
notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee });
}
// Notify moderators, banee
if(this.config.admin_channel[event.server]) {
channels = _.without(channels, adminChannel);
dbot.api.report.notify(server, adminChannel, notifyString);
dbot.say(event.server, adminChannel, notifyString);
if(!_.isUndefined(timeout)) {
dbot.say(event.server, banee, dbot.t('tbanned_notify', {
'network': network,
'banner': banner,
'reason': reason,
'hours': timeout,
'admin_channel': adminChannel
}));
} else {
dbot.say(event.server, banee, dbot.t('nbanned_notify', {
'network': network,
'banner': banner,
'reason': reason,
'hours': timeout,
'admin_channel': adminChannel
}));
}
}
// Ban the user from all channels
var i = 0;
var banChannel = function(channels) {
if(i >= channels.length) return;
var channel = channels[i];
this.api.ban(server, banee, channel);
this.api.kick(server, banee, channel, reason +
' (network-wide ban requested by ' + banner + ')');
setTimeout(function() {
i++; banChannel(channels);
}, 1000);
}.bind(this);
banChannel(channels);
} else {
event.reply(dbot.t('no_user', { 'user': banee }));
}
}.bind(this));
},
'~nunban': function(event) {
var unbanee = event.params[1],
unbanner = event.user;
this.api.networkUnban(event.server, unbanee, unbanner, function(err) {
if(err) {
event.reply(dbot.t('nunban_error', { 'unbanee': unbanee }));
}
});
},
/*** Kick Stats ***/
// Give the number of times a given user has been kicked and has kicked
// other people.
'~kickcount': function(event) {
var username = event.params[1];
if(!_.has(dbot.db.kicks, username)) {
var kicks = '0';
} else {
var kicks = dbot.db.kicks[username];
}
if(!_.has(dbot.db.kickers, username)) {
var kicked = '0';
} else {
var kicked = dbot.db.kickers[username];
}
event.reply(dbot.t('user_kicks', {
'user': username,
'kicks': kicks,
'kicked': kicked
}));
},
// Output a list of the people who have been kicked the most and those
// who have kicked other people the most.
'~kickstats': function(event) {
var orderedKickLeague = function(list, topWhat) {
var kickArr = _.chain(list)
.pairs()
.sortBy(function(kick) { return kick[1] })
.reverse()
.first(10)
.value();
var kickString = "Top " + topWhat + ": ";
for(var i=0;i<kickArr.length;i++) {
kickString += kickArr[i][0] + " (" + kickArr[i][1] + "), ";
}
return kickString.slice(0, -2);
// Add db entry documenting ban
if (this.config.document_bans) {
var id = uuid.v4();
var banRecord = {
'id': id,
'time': new Date().getTime(),
'server': server,
'banee': banee,
'banner': banner,
'host': host,
'reason': reason
};
this.db.save('nbans', id, banRecord, function () {});
}
event.reply(orderedKickLeague(dbot.db.kicks, 'Kicked'));
event.reply(orderedKickLeague(dbot.db.kickers, 'Kickers'));
// Notify moderators, banee
if (!_.isUndefined(adminChannel)) {
channels = _.without(channels, adminChannel);
} else {
adminChannel = event.channel.name;
}
dbot.api.report.notify('ban', server, event.rUser, adminChannel, notifyString, false, banee);
dbot.say(event.server, adminChannel, notifyString);
if (!_.isUndefined(timeout)) {
dbot.say(event.server, banee, dbot.t('tbanned_notify', {
'network': network,
'banner': banner,
'reason': reason,
'hours': timeout,
'admin_channel': adminChannel
}));
} else {
dbot.say(event.server, banee, dbot.t('nbanned_notify', {
'network': network,
'banner': banner,
'reason': reason,
'hours': timeout,
'admin_channel': adminChannel
}));
}
// err
dbot.say(event.server, 'NickServ', 'FREEZE ' + banee + ' ON ' + reason);
} else {
event.reply(dbot.t('no_user', {
'user': banee
}));
}
};
}
.bind(this));
},
_.each(commands, function(command) {
command.access = 'moderator';
});
'~nunban': function (event) {
var unbanee = event.params[1],
host = event.params[2] || undefined,
unbanner = event.rUser;
commands['~kickcount'].access = 'regular';
commands['~kickstats'].access = 'regular';
this.api.networkUnban(event.server, unbanee, unbanner, host, function (err) {
if (err) {
event.reply(dbot.t('nunban_error', {
'unbanee': unbanee
}));
}
});
},
commands['~ckick'].regex = [/^~ckick ([^ ]+) ([^ ]+) (.+)$/, 4];
commands['~nban'].regex = /^~nban ([\d\.^ ]+)?([^ ]+) (.+)$/;
commands['~quiet'].regex = /^~quiet ([\d\.^ ]+)?(#[^ ]+ )?([^ ]+) ?$/;
commands['~unquiet'].regex = /^~unquiet (#[^ ]+ )?([^ ]+) ?$/;
/*** Kick Stats ***/
return commands;
// Give the number of times a given user has been kicked and has kicked
// other people.
'~kickcount': function (event) {
var username = event.params[1];
if (!_.has(dbot.db.kicks, username)) {
var kicks = '0';
} else {
var kicks = dbot.db.kicks[username];
}
if (!_.has(dbot.db.kickers, username)) {
var kicked = '0';
} else {
var kicked = dbot.db.kickers[username];
}
event.reply(dbot.t('user_kicks', {
'user': username,
'kicks': kicks,
'kicked': kicked
}));
},
// Output a list of the people who have been kicked the most and those
// who have kicked other people the most.
'~kickstats': function (event) {
var orderedKickLeague = function (list, topWhat) {
var kickArr = _.chain(list)
.pairs()
.sortBy(function (kick) {
return kick[1]
})
.reverse()
.first(10)
.value();
var kickString = "Top " + topWhat + ": ";
for (var i = 0; i < kickArr.length; i++) {
kickString += kickArr[i][0] + " (" + kickArr[i][1] + "), ";
}
return kickString.slice(0, -2);
};
event.reply(orderedKickLeague(dbot.db.kicks, 'Kicked'));
event.reply(orderedKickLeague(dbot.db.kickers, 'Kickers'));
},
'~votequiet': function (event) {
var target = event.input[1],
reason = event.input[2];
if (_.has(event.channel.nicks, target)) {
dbot.api.users.resolveUser(event.server, target, function (err, user) {
if (!err && user) {
if (_.include(dbot.access.power_user(), user.primaryNick) || target == dbot.config.name) {
return event.reply('User is immune to votequiet.');
}
if (!_.has(this.voteQuiets, user.id)) {
this.voteQuiets[user.id] = {
'user': user.id,
'reason': reason,
'channel': event.channel,
'yes': [event.rUser.primaryNick],
'no': []
};
event.reply(event.user + ' has started a vote to quiet ' + target + ' for "' + reason + '." Type either "~voteyes ' + target + '" or "~voteno ' + target + '" in the next 90 seconds.');
this.voteQuiets[user.id].timer = setTimeout(function () {
var vq = this.voteQuiets[user.id];
vq.spent = true;
if (vq.yes.length >= 3 && vq.no.length < 2) {
event.reply('Attempt to quiet ' + target + ' succeeded. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
this.api.quietUser(event.server, event.rUser, '10m', event.channel, target, reason + '[votequiet]', function (response) {
clearTimeout(vq.timer);
event.reply(response);
});
} else {
event.reply('Attempt to quiet ' + target + ' failed. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
}
var nString = 'A votequiet was attempted on ' + target + ' in ' + event.channel + '. It was initiated by ' + event.rUser.primaryNick + '. ' +
vq.yes.join(', ') + ' voted yes (' + vq.yes.length + '). ';
if (vq.no.length > 0) {
nString += vq.no.join(', ') + ' voted no (' + vq.no.length + ').'
}
dbot.api.report.notify('votequiet', event.server, event.rUser, event.channel, nString, false, target);
setTimeout(function () {
delete this.voteQuiets[user.id];
}
.bind(this), 600000);
}
.bind(this), 90000);
} else {
if (this.voteQuiets[user.id].spent) {
event.reply('A votequiet attempt has already been made on this user in the last 10 minutes.');
} else {
var vq = this.voteQuiets[user.id]
if (!_.include(vq.yes, event.rUser.primaryNick)) {
vq.yes.push(event.rUser.primaryNick);
event.reply('There is already a votequiet attempt active for this user, adding yes vote to existing poll.');
event.reply('Voted yes on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
if (vq.yes.length == 4) {
event.reply('Attempt to quiet ' + target + ' succeeded. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
this.api.quietUser(event.server, event.rUser, '10m', event.channel, target, reason + '[votequiet]', function (response) {
clearTimeout(vq.timer);
vq.spent = true;
setTimeout(function () {
delete this.voteQuiets[user.id];
}
.bind(this), 600000);
event.reply(response);
});
}
} else {
event.reply('There is already a votequiet attempt active for this user, and you already voted yes!');
}
}
}
} else {
event.reply('Target does not seem to be in the channel.');
}
}
.bind(this));
} else {
event.reply('Target does not seem to be in the channel.');
}
},
'~voteyes': function (event) {
var target = event.params[1];
dbot.api.users.resolveUser(event.server, target, function (err, user) {
if (!err && user) {
if (user.id == event.rUser.id) {
return event.reply('You cannot vote on your own silencing. Be good.');
}
if (_.has(this.voteQuiets, user.id) && !this.voteQuiets[user.id].spent) {
var vq = this.voteQuiets[user.id];
if (event.channel != vq.channel) {
return event.reply('Vote must be in ' + vq.channel);
}
if (!_.include(vq.yes, event.rUser.primaryNick) && !_.include(vq.no, event.rUser.primaryNick)) {
vq.yes.push(event.rUser.primaryNick);
event.reply('Voted yes on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
if (vq.yes.length == 4) {
event.reply('Attempt to quiet ' + target + ' succeeded. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
this.api.quietUser(event.server, event.rUser, '10m', event.channel, target, vq.reason + '[votequiet]', function (response) {
clearTimeout(vq.timer);
vq.spent = true;
setTimeout(function () {
delete this.voteQuiets[user.id];
}
.bind(this), 600000);
event.reply(response);
});
}
} else {
event.reply('You have already voted.');
}
} else {
event.reply('There is no active votequiet for this user. You can start one by typing "~votequiet ' + target + ' [reason].');
}
} else {
event.reply('No idea who that is m8');
}
}
.bind(this));
},
'~voteno': function (event) {
var target = event.params[1];
dbot.api.users.resolveUser(event.server, target, function (err, user) {
if (!err && user) {
if (user.id == event.rUser.id) {
return event.reply('You cannot vote on your own silencing. Be good.');
}
if (_.has(this.voteQuiets, user.id) && !this.voteQuiets[user.id].spent) {
var vq = this.voteQuiets[user.id];
if (event.channel != vq.channel) {
return event.reply('Vote must be in ' + vq.channel);
}
if (!_.include(vq.yes, event.rUser.primaryNick) && !_.include(vq.no, event.rUser.primaryNick)) {
vq.no.push(event.rUser.primaryNick);
event.reply('Voted no on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
} else {
event.reply('You have already voted.');
}
} else {
event.reply('There is no active votequiet for this user. You can start one by typing "~votequiet ' + target + ' [reason].');
}
} else {
event.reply('No idea who that is m8');
}
}
.bind(this));
}
};
_.each(commands, function (command) {
command.access = 'moderator';
});
commands['~kickcount'].access = 'regular';
commands['~kickstats'].access = 'regular';
commands['~votequiet'].access = 'regular';
commands['~voteyes'].access = 'regular';
commands['~voteno'].access = 'regular';
commands['~quiet'].access = 'voice';
commands['~timeout'].access = 'voice';
commands['~unquiet'].access = 'voice';
commands['~nban'].access = 'power_user';
commands['~nunban'].access = 'power_user';
commands['~ckick'].regex = /^ckick (#[^ ]+ )?([^ ]+) ?(.*)?$/;
commands['~nban'].regex = /^nban (\d[\d\.dhmsy]+)? ?([^ ]+) (.+)$/;
commands['~quiet'].regex = /^quiet (\d[\d\.hmsy]+)? ?(#[^ ]+ )?([^ ]+) ?(.*)?$/;
commands['~timeout'].regex = /^timeout ([^ ]+) ?(.*)?$/;
commands['~unquiet'].regex = /^unquiet (#[^ ]+ )?([^ ]+) ?$/;
commands['~votequiet'].regex = [/^votequiet ([^ ]+) (.+)$/, 3];
return commands;
};
exports.fetch = function(dbot) {
return commands(dbot);
exports.fetch = function (dbot) {
return commands(dbot);
};

View File

@ -1,15 +1,18 @@
{
"dbKeys": [ "kicks", "kickers", "hosts", "tempBans" ],
"dependencies": [ "command", "report", "users" ],
"help": "http://github.com/reality/depressionbot/blob/master/modules/kick/README.md",
"ignorable": true,
"countSilently": true,
"admin_channel": {
"aberwiki": "#fishbox"
},
"quietBans": [
"#wherever"
],
"network_name": {
"aberwiki": "OAOSIDL"
},
"chanserv": "ChanServ",
"document_bans": false
"document_bans": false,
"dbType": "redis",
"requireWebLogin": true,
"webAccess": "power_user",
"timeoutTime": "10m"
}

View File

@ -1,132 +1,270 @@
var _ = require('underscore')._;
var kick = function(dbot) {
this.hosts = dbot.db.hosts;
this.tempBans = dbot.db.tempBans;
this.api = {
'ban': function(server, user, channel) {
dbot.say(server, this.config.chanserv, 'ban ' + channel + ' ' + user);
},
var kick = function (dbot) {
if (!_.has(dbot.db, 'recentTimeouts')) {
dbot.db.recentTimeouts = {};
}
this.recentTimeouts = dbot.db.recentTimeouts;
'quiet': function(server, user, channel) {
dbot.say(server, this.config.chanserv, 'quiet ' + channel + ' ' + user);
},
this.api = {
'ban': function (server, host, channel) {
dbot.instance.connections[server].send('MODE ' + channel + ' +b *!*@' + host);
},
'unquiet': function(server, user, channel) {
dbot.say(server, this.config.chanserv, 'unquiet ' + channel + ' ' + user);
},
'quiet': function (server, host, channel) {
dbot.instance.connections[server].send('MODE ' + channel + ' +q *!*@' + host);
},
'kick': function(server, user, channel, msg) {
dbot.instance.connections[server].send('KICK ' + channel + ' ' + user + ' :' + msg);
},
'unquiet': function (server, host, channel) {
dbot.instance.connections[server].send('MODE ' + channel + ' -q *!*@' + host);
},
'unban': function(server, host, channel) {
dbot.say(server, this.config.chanserv, 'unban ' + channel + ' *!*@' + host);
},
'devoice': function (server, nick, channel) {
dbot.instance.connections[server].send('MODE ' + channel + ' -v ' + nick);
},
'networkUnban': function(server, unbanee, unbanner, callback) {
var channels = dbot.config.servers[server].channels,
network = this.config.network_name[server] || server,
adminChannel = this.config.admin_channel[server];
'voice': function (server, nick, channel) {
dbot.instance.connections[server].send('MODE ' + channel + ' +v ' + nick);
},
if(_.has(this.hosts, server) && _.has(this.hosts[server], unbanee)) {
var host = this.hosts[server][unbanee];
'kick': function (server, user, channel, msg) {
dbot.instance.connections[server].send('KICK ' + channel + ' ' + user + ' :' + msg);
},
// Notify Staff
if(!_.isUndefined(adminChannel)) {
var notifyString = dbot.t('nunbanned', {
'network': network,
'unbanee': unbanee,
'unbanner': unbanner
});
dbot.api.report.notify(server, adminChannel, notifyString);
dbot.say(server, adminChannel, notifyString);
'kill': function (server, user, reason) {
dbot.instance.connections[server].send('kill ' + user + ' ' + reason);
},
'unban': function (server, host, channel) {
// TODO: Wrest control from chanserv
//dbot.say(server, this.config.chanserv, 'unban ' + channel + ' *!*@' + host);
dbot.instance.connections[server].send('MODE ' + channel + ' -b *!*@' + host);
},
'quietUser': function (server, quieter, duration, channel, quietee, reason, callback) {
dbot.api.nickserv.getUserHost(server, quietee, function (host) {
// Add host record entry
if (host) {
this.hosts[server][quietee] = host;
if (!_.isUndefined(duration) && !_.isNull(duration)) {
duration = duration.trim();
var msTimeout = new Date(new Date().getTime() + (parseFloat(duration) * 60000));
if (_.has(dbot.modules, 'remind')) {
msTimeout = dbot.api.remind.parseTime(duration);
if (!msTimeout) {
return callback('Invalid time. Remember you must give e.g. 5m now.');
}
duration = duration.replace(/([\d]+)d/, '$1 years').replace(/([\d]+)d/, '$1 days').replace(/([\d]+)h/, '$1 hours ').replace(/([\d]+)m/, '$1 minutes ').replace(/([\d]+)s/, '$1 seconds').trim();
} else {
duration += ' minutes';
}
var vStatus = dbot.instance.connections[server].channels[channel].nicks[quietee].voice;
dbot.api.timers.addTimeout(msTimeout, function () {
if (_.has(this.hosts[server], quietee)) {
if (_.include(this.config.quietBans, channel)) {
this.api.unban(server, this.hosts[server][quietee], channel);
this.api.voice(server, quietee, channel);
} else {
this.api.unquiet(server, this.hosts[server][quietee], channel);
}
// Notify Unbanee
dbot.say(server, unbanee, dbot.t('nunban_notify', {
'network': network,
'unbanee': unbanee,
'unbanner': unbanner
}));
// Unban
var i = 0;
var unbanChannel = function(channels) {
if(i >= channels.length) return;
var channel = channels[i];
this.api.unban(server, host, channel);
setTimeout(function() {
i++; unbanChannel(channels);
}, 1000);
}.bind(this);
unbanChannel(channels);
callback(null); // Success
} else {
// Attempt to look up the host on-the-fly
dbot.api.nickserv.getUserHost(server, unbanee, function(host) {
if(host) {
if(!_.has(this.hosts, server)) this.hosts[server] = {};
this.hosts[server][unbanee] = host;
this.api.networkUnban(server, unbanee, unbanner);
} else {
callback(true); // No host could be found
}
dbot.api.users.resolveUser(server, dbot.config.name, function (err, user) {
dbot.api.report.notify('unquiet', server, user, channel,
dbot.t('unquiet_notify', {
'unquieter': dbot.config.name,
'quietee': quietee
}), false, quietee);
});
}
}
}
};
.bind(this));
callback(dbot.t('tquieted', {
'quietee': quietee,
'minutes': duration
}));
dbot.api.report.notify('quiet', server, quieter.primaryNick, channel,
dbot.t('tquiet_notify', {
'minutes': duration,
'quieter': quieter.primaryNick,
'quietee': quietee,
'reason': reason
}), false, quietee);
} else {
callback(dbot.t('quieted', {
'quietee': quietee
}));
dbot.api.report.notify('quiet', server, quieter.primaryNick, channel,
dbot.t('quiet_notify', {
'quieter': quieter.primaryNick,
'quietee': quietee,
'reason': reason
}), false, quietee);
}
this.internalAPI = {
'addTempBan': function(server, banee, timeout) {
dbot.api.timers.addTimeout(timeout, function() {
this.api.networkUnban(server, banee, dbot.config.name, function(err) {});
delete this.tempBans[server][banee];
}.bind(this));
}.bind(this)
};
this.listener = function(event) {
if(event.kickee == dbot.config.name) {
dbot.instance.join(event, event.channel);
event.reply(dbot.t('kicked_dbot', { 'botname': dbot.config.name }));
dbot.db.kicks[dbot.config.name] += 1;
this.api.devoice(server, quietee, channel);
if (_.include(this.config.quietBans, channel)) {
this.api.ban(server, this.hosts[server][quietee], channel);
} else {
this.api.quiet(server, host, channel);
}
if (reason.indexOf('#warn') !== -1) {
dbot.api.warning.warn(server, quieter, quietee,
'Quieted in ' + channel + ' for ' + reason, channel,
function () {});
}
} else {
if(!_.has(dbot.db.kicks, event.kickee)) {
dbot.db.kicks[event.kickee] = 1;
} else {
dbot.db.kicks[event.kickee] += 1;
}
if(!_.has(dbot.db.kickers, event.user)) {
dbot.db.kickers[event.user] = 1;
} else {
dbot.db.kickers[event.user] += 1;
}
if(!this.config.countSilently) {
event.reply(event.kickee + '-- (' + dbot.t('user_kicks', {
'user': event.kickee,
'kicks': dbot.db.kicks[event.kickee],
'kicked': dbot.db.kickers[event.kickee]
}) + ')');
}
event.reply(dbot.t('no_user', {
'user': quietee
}));
}
}.bind(this);
this.on = 'KICK';
}
.bind(this));
},
this.onLoad = function() {
_.each(this.tempBans, function(bans, server) {
_.each(bans, function(timeout, nick) {
timeout = new Date(timeout);
this.internalAPI.addTempBan(server, nick, timeout);
}, this);
}, this);
}.bind(this);
'networkUnban': function (server, unbanee, unbanner, manualHost, callback) {
var channels = dbot.config.servers[server].channels,
network = this.config.network_name[server] || server,
adminChannel = dbot.config.servers[server].admin_channel;
if (!_.isUndefined(manualHost)) {
this.hosts[server][unbanee] = manualHost;
}
if (_.has(this.hosts, server) && _.has(this.hosts[server], unbanee) && _.isString(this.hosts[server][unbanee])) {
var host = this.hosts[server][unbanee];
// Notify Staff
if (_.isUndefined(adminChannel)) {
adminChannel = event.channel.name;
}
var notifyString = dbot.t('nunbanned', {
'network': network,
'unbanee': unbanee,
'host': host,
'unbanner': unbanner.currentNick
});
dbot.api.report.notify('unban', server, unbanner, adminChannel, notifyString, false, unbanee);
dbot.say(server, adminChannel, notifyString);
// Notify Unbanee
dbot.say(server, unbanee, dbot.t('nunban_notify', {
'network': network,
'unbanee': unbanee,
'unbanner': unbanner.currentNick
}));
// Unban
var i = 0;
var unbanChannel = function (channels) {
if (i >= channels.length)
return;
var channel = channels[i];
this.api.unban(server, host, channel);
setTimeout(function () {
i++;
unbanChannel(channels);
}, 1000);
}
.bind(this);
unbanChannel(channels);
dbot.say(server, 'NickServ', 'FREEZE ' + unbanee + ' OFF');
callback(null); // Success
} else {
// Attempt to look up the host on-the-fly
dbot.api.nickserv.getUserHost(server, unbanee, unbanner, function (host) {
if (host) {
if (!_.has(this.hosts, server))
this.hosts[server] = {};
this.hosts[server][unbanee] = host;
this.api.networkUnban(server, unbanee, unbanner);
} else {
callback(true); // No host could be found
}
}
.bind(this));
}
}
};
this.internalAPI = {
'addTempBan': function (server, banee, timeout) {
dbot.api.users.resolveUser(server, dbot.config.name, function (err, bot) {
dbot.api.timers.addTimeout(timeout, function () {
this.api.networkUnban(server, banee, bot, undefined, function (err) {});
delete this.tempBans[server][banee];
}
.bind(this));
}
.bind(this));
}
.bind(this)
};
this.listener = function (event) {
if (event.kickee == dbot.config.name) {
dbot.instance.join(event, event.channel.name);
event.reply(dbot.t('kicked_dbot', {
'botname': dbot.config.name
}));
dbot.db.kicks[dbot.config.name] += 1;
} else {
if (!_.has(dbot.db.kicks, event.kickee)) {
dbot.db.kicks[event.kickee] = 1;
} else {
dbot.db.kicks[event.kickee] += 1;
}
if (!_.has(dbot.db.kickers, event.user)) {
dbot.db.kickers[event.user] = 1;
} else {
dbot.db.kickers[event.user] += 1;
}
if (!this.config.countSilently) {
event.reply(event.kickee + '-- (' + dbot.t('user_kicks', {
'user': event.kickee,
'kicks': dbot.db.kicks[event.kickee],
'kicked': dbot.db.kickers[event.kickee]
}) + ')');
}
}
}
.bind(this);
this.on = 'KICK';
this.onLoad = function () {
if (!_.has(dbot.db, 'hosts')) {
dbot.db.hosts = {};
_.each(dbot.config.servers, function (v, k) {
dbot.db.hosts[k] = {};
}, this);
}
if (!_.has(dbot.db, 'tempBans'))
dbot.db.tempBans = {};
this.hosts = dbot.db.hosts;
this.tempBans = dbot.db.tempBans;
this.voteQuiets = {};
_.each(this.tempBans, function (bans, server) {
_.each(bans, function (timeout, nick) {
timeout = new Date(timeout);
this.internalAPI.addTempBan(server, nick, timeout);
}, this);
}, this);
if (_.has(dbot.modules, 'web')) {
dbot.api.web.addIndexLink('/bans', 'Ban List');
}
}
.bind(this);
};
exports.fetch = function(dbot) {
return new kick(dbot);
exports.fetch = function (dbot) {
return new kick(dbot);
};

46
modules/kick/pages.js Normal file
View File

@ -0,0 +1,46 @@
var _ = require('underscore')._;
var pages = function (dbot) {
return {
'/bans': function (req, res) {
res.render('servers', {
'servers': _.keys(dbot.config.servers)
});
},
'/underbans': function (req, res) {
this.db.search('nbans', {
'server': server
}, function (ban) {
if (ban.reason.match('#underban')) {
bans.push(ban);
}
}, function () {
res.render('bans', {
'server': server,
'bans': bans
});
});
},
'/bans/:server': function (req, res) {
var server = req.params.server,
bans = [];
this.db.search('nbans', {
'server': server
}, function (ban) {
bans.push(ban);
}, function () {
res.render('bans', {
'server': server,
'bans': bans
});
});
}
}
};
exports.fetch = function (dbot) {
return pages(dbot);
};

View File

@ -5,16 +5,39 @@
"na'vi": "Tuteol {user}it tsrame'i {kicks} hìmtxan ulte sute tsrame'i {kicked} hìmtxan.",
"cy": "Cafwyd {user} ei gicio {kicks} gwaith ac wedi cicio pobl {kicked} gwaith.",
"nl": "{user} is {kicks} keer gekickt en heeft anderen {kicked} keer gekickt.",
"de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt."
"de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt.",
"fr": "{user} a été kické {kicks} fois et a kické des personnes {kicked} fois.",
"it": "{user} ha ricevuto {kicks} pedata/e e ha dato {kicked} pedata/e a altri utenti"
},
"quieted": {
"en": "Quieted {quietee}. Remember: don't be a coconut."
"en": "Quieted {quietee}. Remember: don't be a coconut.",
"fr": "{quietee} a été rendu silencieux. Rappelle-toi : ne sois pas têtu.",
"it": "{quietee} è stato silenziato. Ricordati: non essere testardo",
"de": "{quietee} stummgestellt. Denk dran: Sei kein Arschloch."
},
"tquieted": {
"en": "Quieted {quietee} for {minutes} minutes. Remember: don't be a coconut."
"en": "Quieted {quietee} for {minutes}. Remember: don't be a coconut.",
"fr": "{quietee} a été rendu silencieux pour {minutes} minutes. Rappelle-toi : ne sois pas têtu.",
"it": "{quietee} è stato silenziato per {minutes} minuto/i. Ricordati: non essere testardo",
"de": "{quietee} für {minutes} Minuten stummgestellt. Denk dran: Sei kein Arschloch."
},
"quiet_notify": {
"en": "{quieter} has quieted {quietee}. The reason given was \"{reason}\".",
"de": "{quieter} hat {quietee} stummgestellt. Der Grund ist \"{reason}\"."
},
"tquiet_notify": {
"en": "{quieter} has quieted {quietee} for {minutes} minutes. The reason given was \"{reason}\".",
"de": "{quieter} hat {quietee} für {minutes} Minuten stummgestellt. Der Grund ist \"{reason}\"."
},
"unquieted": {
"en": "Unquieted {quietee}. Remember: don't be a coconut."
"en": "Unquieted {quietee}. Remember: don't be a coconut.",
"fr": "{quietee} peut maintenant parler. Rappelle-toi : ne sois pas têtu.",
"it": "{quietee} può nuovamente parlare. Ricordati: non essere testardo.",
"de": "{quietee} ist nicht mehr stummgestellt. Denk dran: Sei kein Arschloch."
},
"unquiet_notify": {
"en": "{unquieter} has unquieted {quietee}.",
"de": "{unquieter} hat Stummstellung von {quietee} aufgehoben."
},
"kicked_dbot": {
"en": "Thou shalt not kick {botname}",
@ -22,52 +45,71 @@
"na'vi": "Ngal {botname}it ke tsun tsrive'i",
"cy": "Ni ddylech cicio {botname}",
"nl": "Gij zult {botname} niet kicken",
"de": "Du sollst {botname} nicht kicken"
"de": "Du sollst {botname} nicht kicken",
"fr": "Tu ne kickeras pas {botname}",
"it": "Non dare pedata a {botname}"
},
"ckicked": {
"en": "Attention: {kicker} has kicked {kickee} from {channel}. The reason given was: \"{reason}.\"",
"cy": "Sylw: {kicker} wedi cicio'r {kickee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"",
"de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}.\""
"en": "{kicker} has kicked {kickee}. The reason given was: \"{reason}\".",
"cy": "Sylw: {kicker} wedi cicio'r {kickee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}\".",
"de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}\".",
"fr": "Attention : {kicker} a kické {kickee} de {channel}. Raison donnée : \"{reason}\".",
"it": "Attenzione : {kicker} ha dato una pedata a {kickee} di {channel}. Motivo : \"{reason}\"."
},
"cbanned": {
"en": "Attention: {banner} has banned {banee} from {channel}. The reason given was \"{reason}.\"",
"cy": "Sylw: {banner} wedi gwahardd {banee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"",
"de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}.\""
"en": "Attention: {banner} has banned {banee} from {channel}. The reason given was \"{reason}\".",
"cy": "Sylw: {banner} wedi gwahardd {banee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}\".",
"de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}\".",
"fr": "Attention : {banner} a banni {banee} de {channel}. Raison donnée : \"{reason}\".",
"it": "Attenzione : {banner} ha bandito {banee} da {channel}. Motivo : \"{reason}\"."
},
"tbanned": {
"en": "Attention: {banner} has banned {banee} from the {network} network for {hours} hours. The reason given was \"{reason}.\""
"en": "Attention: {banner} has banned {banee} (host: {host}) from the {network} network for {hours}. The reason given was \"{reason}\".",
"de": "Achtung: {banner} hat {banee} vom {network} Netzwerk für {hours} Stunden verbannt. Der Grund war \"{reason}\".",
"fr": "Attention : {banner} a banni {banee} du réseau {network} pour {hours} heures. Raison donnée : \"{reason}\".",
"it": "Attenzione : {banner} ha bandito {banee} dalla rete {network} per {hours} ora/e. Motivo : \"{reason}\"."
},
"tbanned_notify": {
"en": "You have been banned from the {network} network for {hours} hours by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban."
"en": "You have been banned from the {network} network for {hours} by {banner}. The reason given was \"{reason}\". You can join {admin_channel} for more information or to discuss the ban.",
"de": "Du wurdest von {banner} im {network} Netzwerk für {hours} verbannt. Der Grund war \"{reason}\". Du kannst {admin_channel} beitreten um mehr Informatonen zu erhalten oder über die Verbannung zu diskutieren.",
"fr": "Vous avez été banni du réseau {network} pour {hours} heures par {banner}. La raison donnée était \"{reason}\". Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban.",
"it": "Sei stato bandito dalla rete {network} per {hours} ora/e da {banner}. Motivo: \"{reason}\". Puoi ricongiungere {admin_channel} per ulteriori informazioni o discutere sulla messa al bando."
},
"nbanned": {
"en": "Attention: {banner} has banned {banee} from the {network} network. The reason given was \"{reason}.\"",
"cy": "Sylw: {banner} wedi gwahardd {banee} ledled y rhwydwaith. Y rheswm a roddwyd oedd: \"{reason}.\"",
"de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}.\""
"en": "Attention: {banner} has banned {banee} (host: {host}) from the {network} network. The reason given was \"{reason}\".",
"cy": "Sylw: {banner} wedi gwahardd {banee} ledled y rhwydwaith. Y rheswm a roddwyd oedd: \"{reason}\".",
"de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}\".",
"fr": "Attention : {banner} a banni {banee} du réseau {network}. Raison donnée : \"{reason}\".",
"it": "Attentione : {banner} ha bandito {banee} dalla rete {network}. Motivo : \"{reason}\"."
},
"nbanned_notify": {
"en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban."
"en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}\". You can join {admin_channel} for more information or to discuss the ban.",
"de": "Du wurdest von {banner} im {network} Netzwerk verbannt. Der Grund war \"{reason}\". Du kannst {admin_channel} beitreten um mehr Informatonen zu erhalten oder über die Verbannung zu diskutieren.",
"fr": "Vous avez été banni du réseau {network} par {banner}. La raison donnée était \"{reason}\". Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban.",
"it": "Sei stato bandito dalla rete {network} da {banner}. Motivo: \"{reason}\". Puoi ricongiungere {admin_channel} per ulteriori informazioni o discutere sulla messa al bando."
},
"nban_quote": {
"en": "{banee} was banned from the network by {banner} on {time}. The reason given was \"{reason}.\"",
"cy": "Cafodd {banee} ei wahardd o'r rhwydwaith gan {banner} ar {time}. Y rheswm a roddwyd oedd: \"{reason}.\"",
"de": "{banee} wurde von {banner} auf dem gesamten Netzwerk um {time} gebannt. Grund: \"{reason}.\""
},
"no_user": {
"en": "{user} doesn't seem to be online on this server."
"no_user": {
"en": "{user} doesn't seem to be online on this server.",
"de": "{user} scheint auf diesen Server nicht online zu sein.",
"fr": "{user} ne semble pas être connecté à ce serveur.",
"it": "{user} sembra non essere connesso a questo server"
},
"nunbanned": {
"en": "Attention: {unbanee} has been unbanned from the {network} network by {unbanner}."
"en": "Attention: {unbanee} (host: {host}) has been unbanned from the {network} network by {unbanner}.",
"de": "Achtung: {unbanee} wurde im {network} Netzwerk durch {unbanner} entsperrt.",
"fr": "Attention : {unbanee} a été débanni du réseau {network} par {unbanner}.",
"it": "Attenzione : {unbanee} è stato riammesso alla rete {network} da {unbanner}."
},
"nunban_notify": {
"en": "You have been unbanned from the {network} network by {unbanner}."
"en": "You have been unbanned from the {network} network by {unbanner}.",
"de": "Du wurdest im {network} Netzwerk durch {unbanner} entsperrt.",
"fr": "Vous avez été débanni du réseau {network} par {unbanner}.",
"it": "Sei stato riammesso alla rete {network} da {unbanner}."
},
"nunban_error": {
"en": "It appears {unbanee} was not banned using the ~nban command."
},
"quote_recorded": {
"en": "This has been recorded in ~ban_{user}.",
"cy": "Mae hyn wedi cael ei gofnodi yn ~ban_{user}.",
"de": "Dies wurde in ~ban_{user} aufgenommen."
"en": "It appears {unbanee} was not banned using the ~nban command.",
"de": "Es sieht so aus als ob {unbanee} nicht durch die Verwendung des ~nban Befehls verbannt wurde.",
"fr": "Il semble que {unbanee} n'a pas été banni en utilisant la commande ~nban.",
"it": "Sembar che {unbanee} non è stato bandito usano il commando ~nban."
}
}

View File

@ -1,7 +1,9 @@
{
"~ckick": "~ckick [#channel] [username] [reason]",
"~cban": "~cban [#channel] [username] [reason]",
"~nban": "~nban [username] [reason]",
"~nban": "~nban ([time in hours]) [username] [reason]",
"~kickstats": "~kickstats",
"~kickcount": "~kickcount [user]"
"~kickcount": "~kickcount [user]",
"~quiet": "~quiet (time) (#channel) username (reason)",
"~unquiet": "~unquiet (#channel) username"
}

View File

@ -0,0 +1,11 @@
{
"action": "kill",
"sensitivity": 10,
"exempt": [],
"advert_content": [
"________ ______"
],
"cliconn_channel": "#dnsbl",
"cliconn_patterns": [],
"exempt_channels": []
}

View File

@ -0,0 +1,159 @@
/**
* Module name: kill_namespam
* Description: destroy those wot hilight too many nicks at once . usually
* advertising their rubbish irc server (do not)
*/
var _ = require('underscore')._;
var kill_namespam = function(dbot) {
this.saveConfig = function() { // eugh
dbot.customConfig.modules.kill_namespam = this.config;
dbot.modules.admin.internalAPI.saveConfig();
}.bind(this);
this.matchedKill = {};
this.listener = function(event) {
if(event.action == 'PRIVMSG') {
// Here we listen for atropos
if(event.channel == this.config.cliconn_channel) {
if(event.message.match('▶')) {
var matchedPattern = _.find(this.config.cliconn_patterns,
function(p) { try { return event.message.match(p); } catch(e) {}; }); // ok.jpg
if(matchedPattern) {
var nick = event.message.split(' ')[2];
dbot.api.nickserv.getUserHost(event.server, nick, function(host) {
var userIsAuthenticated = host && host.startsWith('tripsit/');
if (userIsAuthenticated) {
event.reply(dbot.t('clikill_spared', {
'user': nick,
'pattern': matchedPattern
}));
} else {
if(!this.matchedKill[host]) {
// Defer killing this connection until after they join a non-exempted channel
this.matchedKill[host] = {
ip: event.message.split(' ')[1],
server: event.server,
matchedPattern: matchedPattern,
rUser: event.rUser
};
}
}
}, true);
}
}
}
// This is the namespam
if(event.channel == event.user) return; // return if pm
if(_.includes(this.config.exempt, event.user)) return;
var message;
var naughty = false;
// Check distinctive spam content match
if(_.any(this.config.advert_content, function(spam) { return event.message.indexOf(spam) != -1; })) {
message = dbot.t('spamcont_act', {
'user': event.user,
'channel': event.channel,
'action': this.config.action
}) + ' ' + dbot.t('sasl_hint');
naughty = true;
}
// Name highlight spam
if(_.filter(event.message.split(' '), function(word) { return _.has(event.channel.nicks, word); }).length > this.config.sensitivity) {
message = dbot.t('namespam_act', {
'user': event.user,
'channel': event.channel,
'action': this.config.action,
'sensitivity': this.config.sensitivity
}) + ' ' + dbot.t('sasl_hint');
naughty = true;
}
if(naughty) {
switch(this.config.action) {
case 'kickban':
dbot.api.kick.ban(event.server, event.host, event.channel);
dbot.api.kick.kick(event.server, event.user, message);
break;
case 'kill':
dbot.api.kick.kill(event.server, event.user, message);
default: break;
}
dbot.api.report.notify('spam', event.server, event.user, event.channel, message, event.host, event.user);
}
} else if (event.action == 'JOIN') {
if(this.matchedKill[event.host]) {
if(this.config.exempt_channels.indexOf(event.channel) == -1) {
var kill = this.matchedKill[event.host];
delete this.matchedKill[event.host];
// Alternatively you can just do dbot.api.kick.kill(event.server, event.user, message);
dbot.say(event.server, 'operserv', 'akill add *@'+ kill.ip +' !P Naughty Nelly Auto-kill v6.2. Matched pattern: /'+ kill.matchedPattern +'/');
var msg = dbot.t('clikill_act', {
'ip': kill.ip,
'pattern': kill.matchedPattern
});
dbot.api.report.notify('autokill', kill.server, kill.rUser,
dbot.config.servers[kill.server].admin_channel, msg, kill.ip, kill.ip);
}
}
} else if (event.action == 'QUIT') {
if(this.matchedKill[event.host]) {
delete this.matchedKill[event.host];
}
}
}.bind(this);
this.on = ['PRIVMSG', 'JOIN', 'QUIT'];
this.commands = {
'~add_spamkill': function(event) {
this.config.advert_content.push(event.params.slice(1).join(' '))
this.saveConfig();
event.reply('Users daring to utter the above to be classified as spam.');
},
'~del_spamkill': function(event) {
this.config.advert_content = _.without(this.config.advert_content, event.params.slice(1).join(' '));
this.saveConfig();
event.reply('Users will no longer be killed for this utterance.');
},
'~add_clikill': function(event) {
var pattern = event.params.slice(1).join(' ');
this.config.cliconn_patterns.push(pattern);
this.saveConfig();
event.reply('Client connection notices matching pattern /'+ pattern +'/ shall henceforth get rekt.');
},
'~del_clikill': function(event) {
var pattern = event.params.slice(1).join(' ');
this.config.cliconn_patterns = _.without(this.config.cliconn_patterns, pattern);
this.saveConfig();
event.reply('Client connection notices matching pattern /'+ pattern +'/ will no longer get rekt.');
},
'~list_clikill': function(event) {
event.reply('Currently active "cliconn" kills (to use add/del, provide the pattern, not the index, and do not include the surrounding //');
_.each(this.config.cliconn_patterns, function(pattern, i) {
event.reply('['+i+'] /' + pattern + '/');
});
}
};
_.each(this.commands, function(c) {
c.access = 'moderator';
});
};
exports.fetch = function(dbot) {
return new kill_namespam(dbot);
};

View File

@ -0,0 +1,17 @@
{
"namespam_act": {
"en": "{user} triggered nickname hilight anti-spam (greater than {sensitivity}). Action: {action}."
},
"spamcont_act": {
"en": "{user} triggered advertising anti-spam (content). Action: {action}"
},
"clikill_act": {
"en": "Added K-Line for {ip}, due to matching pattern: /{pattern}/"
},
"clikill_spared": {
"en": "{user} spared from clikill matched pattern: /{pattern}/"
},
"sasl_hint": {
"en": "You have been killed by our spam filter. You can avoid broad VPN filters by using SASL."
}
}

66
modules/lastfm/README.md Normal file
View File

@ -0,0 +1,66 @@
## LastFM
Adds various LastFM functionalities.
### Description
This module provides a command which allows users to show stats of LastFM and such stuff.
### Dependencies
It has following dependencies:
+ [request](https://github.com/mikeal/request)
+ [async](https://github.com/caolan/async)
+ [moment](https://github.com/moment/moment)
### config.json
api_key and output prefix can be set.
Example:
```
{
"dependencies": [ "profile" ],
"api_key": "blah",
"outputPrefix": "\u000315,5last.fm\u000f"
}
```
### Commands
#### ~lastfm [user]
Display all scrobbles of a user.
Example:
+ ~lastfm reality
#### ~scrobbliest
Displays the users with the most scrobbles.
Example:
+ ~scrobbliest
#### ~suggestion
Displays a suggestion based on the listened scrobbles.
Example:
+ ~suggestion
#### ~listening
Displays the currently/last played song of the posting user.
Example:
+ ~listening
#### ~taste [user]
Compares two users (the posting user and the defined user).
Example:
+ ~taste reality
#### ~tastiest
Displays the users that matches the most in music taste.
Example:
+ ~tastiest
#### ~artists [user]
Compares two users (the posting user and the defined user) and displays their matching artists.
Example:
+ ~artists reality
### TODO

View File

@ -0,0 +1,5 @@
{
"dependencies": [ "profile", "youtube", "spotify" ],
"api_key": "blah",
"outputPrefix": "\u000315,5last.fm\u000f"
}

526
modules/lastfm/lastfm.js Normal file
View File

@ -0,0 +1,526 @@
/**
* Module Name: Last.FM
* Description: Various lastfm functionality.
*/
var _ = require('underscore')._,
request = require('request'),
async = require('async'),
moment = require('moment');
var lastfm = function(dbot) {
this.ApiRoot = 'http://ws.audioscrobbler.com/2.0/';
this.internalAPI = {
'getLastFM': function(server, nick, callback) {
dbot.api.profile.getProfile(server, nick, function(err, user, profile) {
if(user) {
if(profile && _.has(profile.profile, 'lastfm') && _.isString(profile.profile.lastfm)) {
callback(user, profile.profile.lastfm.toLowerCase());
} else {
callback(user, null);
}
} else {
callback(null, null);
}
});
}
};
this.api = {
'getRandomArtistTrack': function(mbid, callback) {
request.get(this.ApiRoot, {
'qs': {
'method': 'artist.gettoptracks',
'mbid': mbid,
'api_key': this.config.api_key,
'format': 'json',
'limit': 10
},
'json': true
}, function(err, res, body) {
if(_.has(body, 'toptracks') && _.has(body.toptracks, 'track')) {
var tracks = body.toptracks.track;
choice = _.random(0, tracks.length - 1),
track = tracks[choice];
callback(null, track);
} else {
callback('idk', body);
}
});
},
'getSimilarArtists': function(mbid, callback) {
request.get(this.ApiRoot, {
'qs': {
'method': 'artist.getsimilar',
'mbid': mbid,
'api_key': this.config.api_key,
'format': 'json',
'limit': 10
},
'json': true
}, function(err, res, body) {
if(_.has(body, 'similarartists') && _.has(body.similarartists, 'artist')) {
callback(null, body.similarartists.artist);
} else {
callback('idk', body);
}
});
},
'getListening': function(username, callback) {
request.get(this.ApiRoot, {
'qs': {
'user': username,
'limit': 2,
'nowplaying': true,
'method': 'user.getrecenttracks',
'api_key': this.config.api_key,
'format': 'json'
},
'json': true
}, function(err, res, body) {
if(_.has(body, 'error') && body.error == 6) {
callback('no_user', null);
} else if(_.has(body, 'recenttracks') && _.has(body.recenttracks, 'track')
&& !_.isUndefined(body.recenttracks.track[0])) {
callback(null, body.recenttracks.track[0]);
} else {
callback('no_listen', null);
}
});
},
/*
'tasteCompare': function(user, oUser, callback) {
request.get(this.ApiRoot, {
'qs': {
'type1': 'user',
'type2': 'user',
'value1': user,
'value2': oUser,
'method': 'tasteometer.compare',
'api_key': this.config.api_key,
'format': 'json'
},
'json': true
}, function(err, res, body) {
console.log(body);
if(_.has(body, 'error') && body.error == 6 || body.error == 7) {
callback('no_user', user, null);
} else if(_.has(body, 'comparison') && _.has(body.comparison, 'result')) {
callback(null, body.comparison.result);
} else {
callback('idk', null);
}
});
},
*/
'getInfo': function(lfm, callback) {
request.get(this.ApiRoot, {
'qs': {
'user': lfm,
'method': 'user.getinfo',
'api_key': this.config.api_key,
'format': 'json'
},
'json': true
}, function(err, res, body) {
if(_.has(body, 'error') && body.error == 6 || body.error == 7) {
callback('no_user', null);
} else if(_.has(body, 'user')) {
callback(null, body.user);
} else {
callback('idk', null);
}
});
}
};
this.commands = {
'~lastfm': function(event) {
var user = event.rUser,
lfm = event.rProfile.lastfm;
if(event.res[0]) {
user = event.res[0].user;
lfm = event.res[0].lfm;
}
this.api.getInfo(lfm, function(err, profile) {
if(!err) {
console.log(profile);
event.reply(dbot.t('lfm_profile', {
'user': user.currentNick,
'plays': profile.playcount.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"),
'date': moment(profile.registered['#text'] * 1000).format('DD/MM/YYYY'),
'link': profile.url
}));
} else {
if(err == 'no_user') {
event.reply(dbot.t('lfm_unknown'));
} else if(err == 'no_listen') {
event.reply(dbot.t('no_listen', { 'user': event.user }));
}
}
});
},
'~scrobbliest': function(event) {
dbot.api.profile.getAllProfilesWith('lastfm', function(profiles) {
if(profiles) {
var plays = [];
async.each(profiles, function(profile, done) {
this.api.getInfo(profile.profile.lastfm, function(err, lProfile) {
if(!err) {
plays.push({
'user': profile.id,
'plays': parseInt(lProfile.playcount)
});
}
done();
});
}.bind(this), function() {
var scrobbliest = _.chain(plays)
.sortBy(function(p) { return p.plays; })
.reverse()
.first(10)
.value();
async.each(scrobbliest, function(item, done) {
dbot.api.users.getUser(item.user, function(err, user) {
item.user = user;
done();
});
}, function() {
var output = dbot.t('lfm_scrobbliest');
_.each(scrobbliest, function(item) {
output += item.user.currentNick + ' (' +
item.plays.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")+ '), ';
});
event.reply(output.slice(0, -2));
});
}.bind(this));
} else {
event.reply('no suitable profiles');
}
}.bind(this));
},
'~suggestion': function(event) {
this.api.getListening(event.rProfile.lastfm, function(err, track) {
if(!err) {
this.api.getSimilarArtists(track.artist.mbid, function(err, similar) {
if(!err) {
var choice = _.random(0, similar.length - 1);
this.api.getRandomArtistTrack(similar[choice].mbid, function(err, track) {
if(!err) {
var output = dbot.t('lfm_suggestion', {
'user': event.user,
'name': track.name,
'artist': track.artist.name
});
var term = track.name + ' ' + track.artist.name;
async.parallel({
youtube: function(cb) {
dbot.api.youtube.search(term, function(body) {
if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) {
var link = body.items[0].id.videoId
if(link) {
cb(null,"https://youtu.be/" + link);
} else {
cb(null, undefined);
}
}
});
},
spotify: function(cb) {
dbot.api.spotify.spotifySearch(term, function(body, url, uri) {
if(body) {
if (!dbot.modules.minify) {
cb(null, { url: url, uri:uri });
} else {
dbot.modules.minify.api.minify(url, "bitly", function(mini) {
cb(null, { url:mini || url, uri:uri });
});
}
} else {
cb(null, undefined);
}
});
}
}, function(err, results) {
if (results.youtube || results.spotify) output += " - "
if (results.youtube) output += results.youtube;
if (results.spotify) {
if (results.youtube) output += " | ";
output += results.spotify.url + " - " + results.spotify.uri;
}
event.reply(output);
});
} else {
event.reply('Couldn\'t get any suggested tracks.');
console.log(err);
}
});
} else {
event.reply('Couldn\'t find any similar artists to what you\'re listening to.');
console.log(err);
}
}.bind(this));
} else {
if(err == 'no_user') {
event.reply(dbot.t('lfm_unknown'));
} else if(err == 'no_listen') {
event.reply(dbot.t('no_listen', { 'user': event.user }));
}
}
}.bind(this));
},
'~listening': function(event) {
var user = event.rUser,
lfm = event.rProfile.lastfm;
if(event.res[0]) {
user = event.res[0].user;
lfm = event.res[0].lfm;
}
this.api.getListening(lfm, function(err, track) {
if(!err) {
var term = track.name + ' ' + track.artist['#text'],
output = '';
if(_.has(track, '@attr') && _.has(track['@attr'], 'nowplaying') && track['@attr'].nowplaying == 'true') {
output = dbot.t('now_listening', {
'user': user.currentNick,
'track': track.name,
'artist': track.artist['#text']
});
} else {
output = dbot.t('last_listened', {
'user': user.currentNick,
'track': track.name,
'artist': track.artist['#text']
});
}
async.parallel({
youtube: function(cb) {
dbot.api.youtube.search(term, function(body) {
if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) {
var link = body.items[0].id.videoId
if(link) {
cb(null,"https://youtu.be/" + link);
} else {
cb(null, undefined);
}
}
});
},
spotify: function(cb) {
dbot.api.spotify.spotifySearch(term, function(body, url, uri) {
if(body) {
if (!dbot.modules.minify) {
cb(null, { url: url, uri:uri });
} else {
dbot.modules.minify.api.minify(url, "bitly", function(mini) {
cb(null, { url:mini || url, uri:uri });
});
}
} else {
cb(null, undefined);
}
});
}
}, function(err, results) {
if (results.youtube || results.spotify) output += " - "
if (results.youtube) output += results.youtube;
if (results.spotify) {
if (results.youtube) output += " | ";
output += results.spotify.url + " - " + results.spotify.uri;
}
event.reply(output);
});
} else {
if(err == 'no_user') {
event.reply(dbot.t('lfm_unknown'));
} else if(err == 'no_listen') {
event.reply(dbot.t('no_listen', { 'user': user.currentNick }));
}
console.log(err);
}
});
},
/*
'~taste': function(event) {
var u1 = event.rUser,
lfm1 = event.rProfile.lastfm,
u2 = event.res[0].user,
lfm2 = event.res[0].lfm;
this.api.tasteCompare(event.rProfile.lastfm, lfm2, function(err, comp) {
if(!err) {
var score = Math.floor(comp.score * 100);
event.reply(dbot.t('taste_compat', {
'user1': event.user,
'user2': u2.currentNick,
'score': score
}));
} else {
if(err == 'no_user') {
event.reply('Unknown Last.FM user.');
} else {
event.reply('Well something went wrong and I don\'t know what it means');
}
}
});
},
'~tastiest': function(event) {
var sortGoodScores = function(goodScores) {
var tastiest = _.chain(goodScores)
.sortBy(function(p) { return p.score; })
.reverse()
.first(10)
.value();
async.each(tastiest, function(pair, done) {
if(!_.isObject(pair.p1)) { // fix this
dbot.api.users.getUser(pair.p1, function(err, user) {
pair.p1 = user;
dbot.api.users.getUser(pair.p2, function(err, user) {
pair.p2 = user;
done();
});
});
} else {
done();
}
}, function() {
var output = 'Most musically compatible users: ';
_.each(tastiest, function(pair) {
output += pair.p1.currentNick + ' & ' +
pair.p2.currentNick + ' (' + pair.score +
'%), ';
});
event.reply(output.slice(0, -2));
});
};
if(this.tastyCache && Date.now() - this.tastyCacheStamp <= 1800000) {
sortGoodScores(this.tastyCache);
} else {
event.reply('Updating tasty cache... Hold onto your coconuts...');
dbot.api.profile.getAllProfilesWith('lastfm', function(profiles) {
if(profiles) {
var scores = {}; // Using this structure first for easier testing in the async
async.eachSeries(profiles, function(p1, next) {
scores[p1.id] = {};
async.eachSeries(profiles, function(p2, subnext) {
if(p1.id == p2.id || p1.profile.lastfm == p2.profile.lastfm || _.has(scores, p2.id) && _.has(scores[p2.id], p1.id)) {
subnext();
} else {
this.api.tasteCompare(p1.profile.lastfm, p2.profile.lastfm, function(err, comp) {
if(!err) {
var score = Math.floor(comp.score * 100);
scores[p1.id][p2.id] = score;
}
subnext();
});
}
}.bind(this), function() { next(); });
}.bind(this), function(err) {
// Now we better structure the scores for sorting
var goodScores = [];
_.each(scores, function(subscores, p1) {
_.each(subscores, function(aScore, p2) {
goodScores.push({
'p1': p1,
'p2': p2,
'score': aScore
});
});
});
this.tastyCache = goodScores;
this.tastyCacheStamp = new Date().getTime();
sortGoodScores(goodScores);
}.bind(this));
} else {
event.reply('No suitable profiles');
}
}.bind(this));
}
},
*/
'~artists': function(event) {
var u1 = event.rUser,
lfm1 = event.rProfile.lastfm,
u2 = event.res[0].user,
lfm2 = event.res[0].lfm;
this.api.tasteCompare(event.rProfile.lastfm, lfm2, function(err, comp) {
if(!err) {
var artists = _.pluck(comp.artists.artist, 'name').join(', ');
event.reply(dbot.t('common_artists', {
'user1': event.user,
'user2': u2.currentNick,
'common': artists
}));
} else {
if(err == 'no_user') {
event.reply(dbot.t('lfm_unknown'));
} else {
event.reply('Well something went wrong and I don\'t know what it means');
}
}
});
}
};
//this.commands['~taste'].regex = [/^taste ([\d\w[\]{}^|\\`_-]+?)/, 2];
this.commands['~artists'].regex = [/^artists ([\d\w[\]{}^|\\`_-]+?)/, 2];
_.each(this.commands, function(command) {
command.resolver = function(event, callback) {
if(event.rProfile && _.has(event.rProfile, 'lastfm')) {
if(event.params[1]) {
this.internalAPI.getLastFM(event.server, event.params[1], function(user, lfm) {
if(user && lfm) {
event.res.push({
'user': user,
'lfm': lfm
});
callback(false);
} else {
if(!user) {
event.reply('Unknown user.');
} else {
event.reply(user.currentNick + ': Set a lastfm username with "~set lastfm username"');
}
callback(true);
}
});
} else {
callback(false);
}
} else {
event.reply(event.user + ': Set a lastfm username with "~set lastfm username"');
callback(true);
}
}.bind(this);
}, this);
};
exports.fetch = function(dbot) {
return new lastfm(dbot);
};

View File

@ -0,0 +1,35 @@
{
"now_listening": {
"en": "{user} is listening to {track} by {artist}",
"de": "{user} hört {track} von {artist}"
},
"last_listened": {
"en": "{user} last listened to {track} by {artist}",
"de": "{user} hörte zuletzt {track} von {artist}"
},
"no_listen": {
"en": "{user} doesn't seem to have listened to anything recently :'(",
"de": "{user} scheint in letzter Zeit nichts gehört zu haben :'("
},
"taste_compat": {
"en": "{user1} and {user2} are {score}% musically compatible!",
"de": "{user1} und {user2} sind {score}% musikalisch kompatibel!"
},
"common_artists": {
"en": "Artists {user1} and {user2} have in common: {common}",
"de": "Künstler, die {user1} und {user2} gemeinsam haben: {common}"
},
"lfm_suggestion": {
"en": "{user}: Try listening to {name} by {artist}",
"de": "{user}: Versuche mal, {name} von {artist} anzuhören"
},
"lfm_profile": {
"en": "{user} has scrobbled {plays} tracks since {date} - {link}"
},
"lfm_scrobbliest": {
"en": "Users with the most played tracks: "
},
"lfm_unknown": {
"en": "Unknown Last.FM user. Please set your Last.FM user by typing '~set lastfm <name>' where <name> is your Last.FM username."
}
}

View File

@ -0,0 +1,5 @@
{
"outputPrefix": "\u00033weed\u000f",
"app_key": "",
"app_id": ""
}

47
modules/leafly/leafly.js Normal file
View File

@ -0,0 +1,47 @@
/**
* Module name: Leafly
* Description: Information from leafly
*/
var _ = require('underscore')._,
request = require('request');
var leafly = function(dbot) {
var ApiRoot = 'http://data.leafly.com/';
this.commands = {
'~strain': function(event) {
request.post(ApiRoot + 'strains', {
'headers': {
'app_key': this.config.app_key,
'app_id': this.config.app_id
},
'body': {
'page': 0,
'take': 1,
'sort': 'rating',
'search': event.input[1]
},
'json': true
}, function(error, response, body) {
if(_.isObject(body) && _.has(body, 'Strains') && body.Strains.length > 0) {
var strain = body.Strains[0],
flavours = _.pluck(strain.Flavors, 'Name').join(', ');
event.reply(dbot.t('strain', {
'name': strain.Name,
'flavours': flavours,
'link': strain.permalink
}));
} else {
event.reply(dbot.t('no_strains'));
}
}.bind(this));
}
};
this.commands['~strain'].regex = [/^strain (.+)$/, 2];
};
exports.fetch = function(dbot) {
return new leafly(dbot);
};

View File

@ -0,0 +1,8 @@
{
"strain": {
"en": "{name} tastes of {flavours} - {link}"
},
"no_strains": {
"en": "No strains found :("
}
}

View File

@ -1,6 +1,5 @@
{
"autoTitle": false,
"dependencies": [ "command" ],
"autoTitle": true,
"ignorable": true,
"outputPrefix": "\u00032link\u000f",
"help": "http://github.com/reality/depressionbot/blob/master/modules/link/README.md"

View File

@ -9,15 +9,15 @@ var request = require('request'),
var link = function(dbot) {
this.urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
this.links = {};
this.links = {};
this.handlers = [];
this.api = {
'addHandler': function(name, regex, handler) {
this.handlers.push({
'name': name,
'regex': regex,
'callback': handler
this.handlers.push({
'name': name,
'regex': regex,
'callback': handler
});
},
@ -26,8 +26,8 @@ var link = function(dbot) {
size = 0,
page = request(link.replace('https', 'http'), function(error, response, body) {
if(!error && response.statusCode == 200) {
body = body.replace(/(\r\n|\n\r|\n)/gm, " ");
var title = body.valMatch(/<title>(.*)<\/title>/, 2);
body = body.replace(/(\r\n|\n\r|\n)/gim, " ");
var title = body.valMatch(/<title>(.*?)<\\?\/title>/, 2);
if(title && title.length < 140) {
callback(ent.decode(title[1]).trim());
}
@ -43,23 +43,50 @@ var link = function(dbot) {
},
'udLookup': function(query, callback) {
var reqUrl = 'http://api.urbandictionary.com/v0/define?term=' +
encodeURI(query);
var reqUrl = 'http://api.urbandictionary.com/v0/define?term=' +
encodeURI(query);
request(reqUrl, function(error, response, body) {
console.log(reqUrl);
try {
var result = JSON.parse(body);
if(_.has(result, 'result_type') && result.result_type != 'no_results') {
if(_.has(result, 'list') && result.list.length > 0) {
callback(result.list[0].word, result.list[0].definition.split('\n')[0]);
} else {
callback(false);
}
} catch(err) { callback(false); }
} catch(err) {
console.log(err);
callback(false);
}
});
},
'parseLink': function(link, callback) {
var handler = false;
for(var i=0;i<this.handlers.length;i++) {
var matches = this.handlers[i].regex.exec(link);
if(matches) {
console.log(this.handlers[i].name);
handler = this.handlers[i];
break;
}
}
if(handler) {
this.handlers[i].callback(matches, this.handlers[i].name, function(parsed) {
callback(parsed);
});
} else {
this.api.getTitle(link, function(title) {
callback(dbot.t('link', { 'link': title } ));
});
}
}
};
var commands = {
'~title': function(event) {
var link = this.links[event.channel.name];
@ -73,9 +100,10 @@ var link = function(dbot) {
event.reply(dbot.t('link', { 'link': title} ));
});
},
'~xkcd': function(event) {
var comicId = event.params[1] || "";
//var comicId = event.params[1] || "";
var comicId = event.params.slice(1).join(' ');
if(comicId == "*") {
request("http://xkcd.com/info.0.json", function(error, response, body){
@ -86,27 +114,86 @@ var link = function(dbot) {
dbot.commands['~xkcd'](event);
}
} catch(err) { };
});
} else {
if(comicId !== "") {
comicId = comicId + "/";
}
var link = "http://xkcd.com/"+comicId+"info.0.json";
request(link, function(error, response, body) {
try {
if (response.statusCode == "200") {
data = JSON.parse(body);
event.reply(dbot.t("xkcd", data));
} else {
event.reply(dbot.t("no-hits"));
}
} catch(err) { };
});
} else {
if (isNaN(parseInt(comicId))) {
request({
url: 'http://www.explainxkcd.com/wiki/api.php',
qs: {
action: 'query',
format: 'json',
generator: 'search',
gsrwhat: 'text',
gsrsearch: comicId,
prop: 'info|categories',
gsrlimit: 50
},
json: true
}, function(err, res, body) {
if(!body) {
event.reply(dbot.t("no-hits"));
return;
}
var pages = _.values(body.query.pages);
// page titles must be of the format "####: $$$$$$"
pages = _.filter(pages, p => p.title.indexOf(':') > 0);
if (pages.length > 0) {
// See if any of these matches are exact title matches
var match = false;
_.each(pages, function(p) {
var title = p.title.slice(p.title.indexOf(':')+2).trim();
if(title.toLowerCase() == comicId.toLowerCase()) {
match = p;
}
});
if (match) {
// We got a match! Get the ID and let's get tf out of here.
comicId = match.title.slice(0, match.title.indexOf(':'));
} else {
comicId = pages[0].title.slice(0, pages[0].title.indexOf(':'));
}
var link = "http://xkcd.com/"+comicId+"/info.0.json";
request(link, function(error, response, body) {
try {
if (response.statusCode == "200") {
data = JSON.parse(body);
event.reply(dbot.t("xkcd", data));
} else {
event.reply(dbot.t("no-hits"));
}
} catch(err) { };
});
} else {
event.reply(dbot.t("no-hits"));
}
});
} else {
if(comicId !== "") {
comicId = comicId + "/";
}
var link = "http://xkcd.com/"+comicId+"info.0.json";
request(link, function(error, response, body) {
try {
if (response.statusCode == "200") {
data = JSON.parse(body);
event.reply(dbot.t("xkcd", data));
} else {
event.reply(dbot.t("no-hits"));
}
} catch(err) { };
});
}
}
},
'~ud': function(event) {
var query = event.input[1];
@ -119,27 +206,18 @@ var link = function(dbot) {
});
}
};
commands['~ud'].regex = [/~ud (.+)/, 2];
commands['~ud'].regex = [/ud (.+)/, 2];
this.commands = commands;
this.listener = function(event) {
var urlMatches = event.message.match(this.urlRegex);
if(urlMatches !== null) {
this.links[event.channel.name] = urlMatches[0];
if(dbot.config.link.autoTitle == true) {
var handlerFound = false;
for(var i=0;i<this.handlers.length;i++) {
var matches = this.handlers[i].regex.exec(urlMatches[0]);
if(matches) {
this.handlers[i].callback(event, matches, this.handlers[i].name);
handlerFound = true; break;
}
}
if(!handlerFound) {
this.api.getTitle(urlMatches[0], function(title) {
event.reply(dbot.t('link', { 'link': title } ));
});
}
console.log('DEBUG: got a link');
if(this.config.autoTitle == true) {
this.api.parseLink(urlMatches[0], function(result) {
event.reply(result);
});
}
}
}.bind(this);

View File

@ -4,19 +4,29 @@
"na'vi": "Oel ke tsun run 'upxare atxin.",
"cy": "Ni chanfuwyd teitl y dudalen",
"nl": "Er is geen paginatitel gevonden.",
"de": "Kein Seitenname gefunden."
"de": "Kein Seitenname gefunden.",
"fr": "Aucun titre de page trouvé.",
"it": "Nessun titolo di pagina trovato."
},
"xkcd": {
"en": "xkcd {num}: {title} https://xkcd.com/{num}"
"en": "xkcd {num}: {title} https://xkcd.com/{num}",
"fr": "xkcd {num}: {title} https://xkcd.com/{num}",
"it": "xkcd {num}: {title} https://xkcd.com/{num}",
"de": "xkcd {num}: {title} https://xkcd.com/{num}"
},
"no-hits": {
"en": "No hits.",
"na'vi": "Oel ke tsun rivum ayuoti.",
"cy": "Dim canlyniadau.",
"nl": "Geen resultaten.",
"de": "Keine Treffer."
"de": "Keine Treffer.",
"fr": "Aucun résultat.",
"it": "Nessun risultato."
},
"link": {
"en": "{link}"
"en": "{link}",
"fr": "{link}",
"it": "{link}",
"de": "{link}"
}
}

Some files were not shown because too many files have changed in this diff Show More