├── .gitignore ├── EasyXdcc-1.0.tar.bz2 ├── EasyXdcc.py ├── LICENSE.md ├── README.md ├── osdircheck.py └── testplugin.py /.gitignore: -------------------------------------------------------------------------------- 1 | temp-changelog.md 2 | *.zip 3 | -------------------------------------------------------------------------------- /EasyXdcc-1.0.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ultrabenosaurus/EasyXdcc/094c106fec116ea62e92f99f9392d51317bd2c57/EasyXdcc-1.0.tar.bz2 -------------------------------------------------------------------------------- /EasyXdcc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | __module_name__ = "EasyXdcc" 3 | __module_version__ = "1.3" 4 | __module_description__ = "Xdcc Queues" 5 | __module_author__ = "Bouliere Tristan " 6 | __module_contributor__ = "Ultrabenosaurus " 7 | import xchat, os, time, pprint, platform 8 | 9 | class t_bot: 10 | def __init__(self, name, serv, chan): 11 | self.name = name 12 | self.chan = chan 13 | self.serv = serv 14 | self.packs = [] 15 | 16 | def match (self, name, chan, serv): 17 | return (self.name == name) & (self.chan == chan) & (self.serv == serv) 18 | 19 | def __eq__ (self, bot): 20 | if (isinstance(bot, t_bot)) : 21 | return (self.name == bot.name) & (self.chan == bot.chan) & (self.serv == bot.serv) 22 | else : 23 | return False 24 | 25 | def add_pack(self, num_pack): 26 | if (type(num_pack) == int): 27 | if not num_pack in self.packs: 28 | self.packs.append(num_pack) 29 | self.packs.sort(reverse=True) 30 | 31 | def del_pack(self, num_pack): 32 | if (type(num_pack) == int): 33 | if self.packs.__contains__(num_pack): 34 | del self.packs[self.packs.index(num_pack)] 35 | 36 | def pop(self): 37 | return self.packs.pop() 38 | 39 | def __len__ (self): 40 | return len(self.packs) 41 | 42 | def isActive(self): 43 | list = xchat.get_list("dcc") 44 | if (list): 45 | for i in list: 46 | if i.nick == self.name: 47 | return (i.status == 0) | (i.status == 1) | (i.status == 4) 48 | return False 49 | 50 | def __repr__(self): 51 | bot_str = "Bot : "+self.name+" [ "+self.serv+", "+self.chan+"]"+"\n" 52 | for pack in reversed(self.packs): 53 | bot_str += " #"+str(pack)+"\n" 54 | return bot_str 55 | 56 | class bot_queue: 57 | def __init__(self): 58 | self.bots = [] 59 | 60 | def search(self, name, chan, serv): 61 | for i in self.bots: 62 | if (i.match(name, chan, serv)): 63 | return i 64 | return None 65 | 66 | def add(self, new_bot): 67 | if isinstance(new_bot, t_bot): 68 | for i in self.bots: 69 | if (i == new_bot): 70 | return 71 | self.bots.append(new_bot) 72 | 73 | def del_bot (self, bot): 74 | if isinstance(bot, t_bot): 75 | if bot in self.bots: 76 | del self.bots[self.bots.index(bot)] 77 | 78 | def __repr__ (self): 79 | queue_str = "\n" 80 | queue_str += "*****************************\n" 81 | queue_str += "* Queue EasyXdcc *\n" 82 | queue_str += "*****************************\n" 83 | queue_str += "\n" 84 | if len(self.bots) == 0: 85 | queue_str += "No pack(s) queued\n" 86 | queue_str += "\n" 87 | else: 88 | for bot in self.bots: 89 | queue_str += repr(bot) 90 | queue_str += "\n" 91 | return queue_str 92 | 93 | def save(self, file_name): 94 | if (type(file_name) == str): 95 | try: 96 | file = open(file_name,'wt') 97 | try: 98 | for bot in self.bots: 99 | file.write(getattr(bot,"name")+"\n") 100 | file.write(getattr(bot,"serv")+"\n") 101 | file.write(getattr(bot,"chan")+"\n") 102 | for pack in getattr(bot,"packs"): 103 | file.write(str(pack)+"\n") 104 | file.write("\n") 105 | finally: 106 | file.close() 107 | except IOError: 108 | pass 109 | 110 | def load(self,file_name): 111 | strip_str = "\n\r" 112 | if (type(file_name) == str): 113 | try: 114 | file = open(file_name,'rt') 115 | try: 116 | etat=0 117 | for buffer in file.readlines(): 118 | if etat==0: 119 | name = buffer.strip(strip_str) 120 | etat = 1 121 | elif etat==1: 122 | serv = buffer.strip(strip_str) 123 | etat = 2 124 | elif etat==2: 125 | chan = buffer.strip(strip_str) 126 | etat = 3 127 | elif etat==3: 128 | bot = t_bot(name,serv,chan) 129 | self.add(bot) 130 | pack = buffer.strip(strip_str) 131 | if pack == "": 132 | etat=0 133 | else: 134 | bot.add_pack(int(pack)) 135 | etat=4 136 | else: 137 | pack = buffer.strip(strip_str) 138 | if pack == "": 139 | etat=0 140 | else: 141 | bot.add_pack(int(pack)) 142 | 143 | finally: 144 | file.close() 145 | except IOError: 146 | pass 147 | 148 | def delqueue(self,file_name): 149 | if (type(file_name) == str): 150 | try: 151 | os.remove(file_name) 152 | except OSError: 153 | pass 154 | 155 | def purgequeue(self, file_name): 156 | self.bots = [] 157 | delqueue() 158 | 159 | 160 | def connect(self): 161 | servchan=[] 162 | for bot in self.bots: 163 | if servchan.__contains__(getattr(bot,"serv")): 164 | servchan[servchan.index(getattr(bot,"serv")) + 1].append(getattr(bot,"chan")) 165 | else: 166 | servchan.append(getattr(bot,"serv")) 167 | servchan.append([getattr(bot,"chan")]) 168 | 169 | for i in range(0,len(servchan),2): 170 | servs = "" 171 | for serv in servchan[i+1]: 172 | servs=servs+serv+"," 173 | servs = servs.strip(",") 174 | xchat.command("servchan "+servchan[i]+" 6667 "+servs) 175 | 176 | def get_bot_current_chan(bot_name): 177 | global queue 178 | if (type(bot_name) != str): 179 | return None 180 | serv = xchat.get_info("host"); 181 | chan = xchat.get_info("channel"); 182 | if serv is None or chan is None: 183 | print("Not Connected!") 184 | return xchat.EAT_ALL 185 | bot = queue.search(bot_name, chan, serv) 186 | if bot is None: 187 | bot = t_bot(bot_name, serv, chan) 188 | queue.add(bot) 189 | return bot 190 | 191 | def search_bot_current_chan(bot_name): 192 | global queue 193 | if (type(bot_name) != str): 194 | return None 195 | serv = xchat.get_info("host"); 196 | chan = xchat.get_info("channel"); 197 | if serv is None or chan is None: 198 | print("Not Connected!") 199 | return xchat.EAT_ALL 200 | return queue.search(bot_name, chan, serv) 201 | 202 | def help(): 203 | print("") 204 | print("*****************************") 205 | print("* EasyXdcc Commands *") 206 | print("*****************************") 207 | print("") 208 | print("Queue a pack :") 209 | print("/XDCC ADD [bot_name] [n°_pack]") 210 | print("") 211 | print("Queue a pack list :") 212 | print("/XDCC ADDL [bot_name] [n°_pack_beg] [n°_pack_end]") 213 | print("") 214 | print("Queue non-sequential pack list :") 215 | print("/XDCC ADDM [bot_name] [n°_pack_1] [n°_pack_2] [...]") 216 | print("") 217 | print("See pack queue :") 218 | print("/XDCC QUEUE") 219 | print("") 220 | print("See pack queue for a bot :") 221 | print("/XDCC QUEUE [bot_name]") 222 | print("") 223 | print("Withdraw a pack from queue :") 224 | print("/XDCC RMP [bot_name] [n°pack]") 225 | print("") 226 | print("Withdraw a pack list from queue :") 227 | print("/XDCC RMPL [bot_name] [n°pack_beg] [N°pack_end]") 228 | print("") 229 | print("Withdraw a non-sequential pack list from queue :") 230 | print("/XDCC RMPM [bot_name] [n°_pack_1] [n°_pack_2] [...]") 231 | print("") 232 | print("Withdraw a bot from queue :") 233 | print("/XDCC RMBOT [bot_name]") 234 | print("") 235 | print("Stop EasyXdcc :") 236 | print("/XDCC STOP") 237 | print("") 238 | print("Start EasyXdcc :") 239 | print("/XDCC START") 240 | print("") 241 | print("Show auto-start status :") 242 | print("/XDCC AUTO") 243 | print("") 244 | print("Toggle auto-start :") 245 | print("/XDCC AUTO [ON|OFF]") 246 | print("") 247 | print("Save Queue :") 248 | print("/XDCC SAVE") 249 | print("") 250 | print("Load Queue :") 251 | print("/XDCC LOAD") 252 | print("") 253 | print("Delete saved Queue file :") 254 | print("/XDCC PURGE") 255 | print("") 256 | 257 | return xchat.EAT_ALL 258 | 259 | def idx_EasyXdcc(word, word_eol, userdata): 260 | argc = len(word) 261 | 262 | if argc == 2: 263 | if word[1] == "start": 264 | return start() 265 | elif word[1] == "stop": 266 | return stop() 267 | elif word[1] == "save": 268 | return save() 269 | elif word[1] == "load": 270 | return load() 271 | elif word[1] == "queue": 272 | return seequeue() 273 | elif word[1] == "help": 274 | return help() 275 | elif word[1] == "purge": 276 | return purgequeue() 277 | elif word[1] == "auto": 278 | return show_auto() 279 | elif argc == 3: 280 | if word[1] == "rmbot": 281 | return rmbot(word[2]) 282 | elif word[1] == "queue": 283 | return seebotqueue(word[2]) 284 | elif word[1] == "auto": 285 | return toggle_auto(word[2]) 286 | elif argc == 4 : 287 | if word[3].isdigit(): 288 | if word[1] == "add": 289 | return add(word[2], int(word[3])) 290 | elif word[1] == "rmp": 291 | return rmp(word[2], int(word[3])) 292 | elif argc >= 5: 293 | if word[3].isdigit() & word[4].isdigit(): 294 | if word[1] == "addl": 295 | return addl(word[2], int(word[3]), int(word[4])) 296 | elif word[1] == "rmpl": 297 | return rmpl(word[2], int(word[3]), int(word[4])) 298 | elif word[1] == "addm": 299 | return addm(word[2], word[3:]) 300 | elif word[1] == "rmpm": 301 | return rmpm(word[2], word[3:]) 302 | 303 | return xchat.EAT_ALL 304 | 305 | def seequeue(): 306 | global queue 307 | print(queue) 308 | return xchat.EAT_ALL 309 | 310 | def seebotqueue(bot_name): 311 | global queue 312 | if (type(bot_name) != str): 313 | print("/XDCC QUEUE [BOT_NAME]") 314 | return xchat.EAT_ALL 315 | else: 316 | bot = search_bot_current_chan(bot_name) 317 | if bot is not None: 318 | print(bot) 319 | return xchat.EAT_ALL 320 | 321 | def show_auto(): 322 | if os.path.exists(sav_dir + "autostart"): 323 | print("EasyXdcc : auto-start is currently ON") 324 | else: 325 | print("EasyXdcc : auto-start is currently OFF") 326 | return xchat.EAT_ALL 327 | 328 | def toggle_auto(switch): 329 | if 'on' == switch: 330 | if not os.path.exists(sav_dir + "autostart"): 331 | file = open(sav_dir + "autostart", 'wt') 332 | file.close() 333 | xchat.command ("MENU -t1 ADD \"EasyXdcc/Auto-Start\" \"xdcc auto on\" \"xdcc auto off\"") 334 | print("EasyXdcc : auto-start enabled") 335 | if 'off' == switch: 336 | if os.path.exists(sav_dir + "autostart"): 337 | os.remove(sav_dir + "autostart") 338 | xchat.command ("MENU -t0 ADD \"EasyXdcc/Auto-Start\" \"xdcc auto on\" \"xdcc auto off\"") 339 | print("EasyXdcc : auto-start disabled") 340 | return xchat.EAT_ALL 341 | 342 | def add(bot_name, num_pack): 343 | global queue 344 | if (type(bot_name) != str) & (type(num_pack) != int): 345 | print("/XDCC ADD BOT_NAME NUM_PACK") 346 | else: 347 | bot = get_bot_current_chan(bot_name) 348 | if bot is not None: 349 | bot.add_pack(num_pack) 350 | print("EasyXdcc : Pack number #"+str(num_pack)+" add to "+bot_name) 351 | return xchat.EAT_ALL 352 | 353 | def addl(bot_name, pbeg, pend): 354 | global queue 355 | if (type(bot_name) != str) & (type(pbeg) != int) & (type(pend) != int): 356 | print("/XDCC ADD BOT_NAME NUM_PACK") 357 | else: 358 | bot = get_bot_current_chan(bot_name) 359 | if bot is not None: 360 | for pack in range(pbeg, pend+1): 361 | bot.add_pack(pack) 362 | print("EasyXdcc : Packs number #"+str(pbeg)+" to #"+str(pend)+" add to "+bot_name) 363 | return xchat.EAT_ALL 364 | 365 | def addm(bot_name, *pack_nums): 366 | global queue 367 | pack_nums = pack_nums[0] 368 | if (type(bot_name) != str) & (type(pack_nums) != tuple) & (type(pack_nums[0]) != int): 369 | print("/XDCC ADDM BOT_NAME PACK_NUM_1 PACK_NUM_2 ...") 370 | else: 371 | bot = get_bot_current_chan(bot_name) 372 | if bot is not None: 373 | for pack in pack_nums: 374 | bot.add_pack(int(pack)) 375 | print("EasyXdcc : add "+str(len(pack_nums))+" Packs to "+bot_name) 376 | return xchat.EAT_ALL 377 | 378 | def rmp(bot_name,num_pack): 379 | if (type(bot_name) != str) & (type(num_pack) != int): 380 | print("/XDCC RMP BOT_NAME NUM_PACK") 381 | else: 382 | bot = search_bot_current_chan(bot_name) 383 | if bot is not None: 384 | bot.del_pack(num_pack) 385 | print("EasyXdcc : Pack number #"+str(num_pack)+" remove from "+bot_name) 386 | return xchat.EAT_ALL 387 | 388 | def rmpl(bot_name,pbeg,pend): 389 | global queue 390 | if (type(bot_name) != str) & (type(pbeg) != int) & (type(pend) != int): 391 | print("/XDCC RMPL BOT_NAME PACK_BEG PACK_END") 392 | else: 393 | bot = search_bot_current_chan(bot_name) 394 | if bot is not None: 395 | for pack in range(pbeg,pend + 1): 396 | bot.del_pack(pack) 397 | print("EasyXdcc : Pack number #"+str(pbeg)+" to #"+str(pend)+" remove from "+bot_name) 398 | return xchat.EAT_ALL 399 | 400 | def rmpm(bot_name, *pack_nums): 401 | global queue 402 | pack_nums = pack_nums[0] 403 | if (type(bot_name) != str) & (type(pack_nums) != tuple) & (type(pack_nums[0]) != int): 404 | print("/XDCC RMPM BOT_NAME PACK_NUM_1 PACK_NUM_2 ...") 405 | else: 406 | bot = get_bot_current_chan(bot_name) 407 | if bot is not None: 408 | for pack in pack_nums: 409 | bot.del_pack(int(pack)) 410 | print("EasyXdcc : remove "+str(len(pack_nums))+" Packs from "+bot_name) 411 | return xchat.EAT_ALL 412 | 413 | def rmbot(bot_name): 414 | global queue 415 | if (type(bot_name) != str): 416 | print("/XDCC RMBOT BOT_NAME") 417 | else: 418 | bot = search_bot_current_chan(bot_name) 419 | if bot is not None: 420 | queue.del_bot(bot) 421 | print("EasyXdcc : "+bot_name+" removed from queue") 422 | return xchat.EAT_ALL 423 | 424 | def save(): 425 | global queue,sav_file 426 | queue.save(sav_file) 427 | print("Queue(s) state saved") 428 | return xchat.EAT_ALL 429 | 430 | def load(): 431 | global queue,sav_file 432 | queue.load(sav_file) 433 | # queue.connect() 434 | print("Queue(s) state loaded") 435 | return xchat.EAT_ALL 436 | 437 | def delqueue(): 438 | global queue,sav_file 439 | queue.delqueue(sav_file) 440 | print("Queue file deleted") 441 | return xchat.EAT_ALL 442 | 443 | def purgequeue(): 444 | global queue,sav_file 445 | queue.purgequeue(sav_file) 446 | print("Queue file deleted") 447 | return xchat.EAT_ALL 448 | 449 | def start(): 450 | global my_hook 451 | if my_hook is None: 452 | my_hook = xchat.hook_timer(10000, launch_dl) 453 | print("EasyXdcc started") 454 | launch_dl(None) 455 | return xchat.EAT_ALL 456 | 457 | def stop(): 458 | global my_hook 459 | if my_hook is not None: 460 | xchat.unhook(my_hook) 461 | my_hook = None 462 | print("EasyXdcc stoped") 463 | return xchat.EAT_ALL 464 | 465 | def launch_dl(userdata): 466 | global queue, my_hook 467 | if None == xchat.get_info("server"): 468 | xchat.unhook(my_hook) 469 | my_hook = xchat.hook_timer(10000,server_check) 470 | else: 471 | for bot in getattr(queue, 'bots'): 472 | if len(bot) == 0: 473 | queue.del_bot(bot) 474 | if not bot.isActive(): 475 | delqueue() 476 | save() 477 | bot_context = xchat.find_context(getattr(bot, 'serv'), getattr(bot, 'chan')) 478 | if bot_context is None: 479 | if xchat.find_context(getattr(bot, 'serv')) is not None: 480 | xchat.command("join " + getattr(bot, 'chan')) 481 | else: 482 | xchat.command("servchan " + getattr(bot, 'serv') + " 6667 " + getattr(bot, 'chan')) 483 | bot_context = xchat.find_context(getattr(bot, 'serv'), getattr(bot, 'chan')) 484 | try: 485 | bot_context.command('msg '+getattr(bot, 'name')+' xdcc send #'+str(bot.pop())) 486 | except AttributeError: 487 | pass 488 | return 1 489 | 490 | def server_check(userdata = None): 491 | global my_hook, no_server 492 | if 0 == no_server: 493 | print("EasyXdcc : waiting for connection") 494 | no_server = 1 495 | if None != xchat.get_info("server"): 496 | xchat.unhook(my_hook) 497 | my_hook = xchat.hook_timer(10000,launch_dl) 498 | no_server = 0 499 | return 1 500 | 501 | def check_dirs(f): 502 | d = os.path.dirname(f) 503 | if not os.path.exists(d): 504 | os.makedirs(d) 505 | 506 | comp = platform.system() 507 | my_hook = None 508 | queue = bot_queue() 509 | no_server = 0 510 | 511 | try: 512 | cmd = os.popen("whoami") 513 | try: 514 | user = cmd.readlines() 515 | user = user[0].strip("\n") 516 | if 'Windows' == comp: 517 | user = user.split("\\")[1] 518 | finally: 519 | cmd.close() 520 | except IOError: 521 | pass 522 | 523 | if 'Windows' == comp: 524 | sav_dir = "C:/Users/"+user+"/.config/EasyXdcc/" 525 | else: 526 | sav_dir = "/home/"+user+"/.config/EasyXdcc/" 527 | check_dirs(sav_dir) 528 | sav_file = sav_dir + "queue" 529 | 530 | xchat.hook_command("XDCC", idx_EasyXdcc, help="/XDCC ") 531 | xchat.command ("MENU -p5 ADD EasyXdcc") 532 | xchat.command ("MENU ADD \"EasyXdcc/Start\" \"xdcc start\"") 533 | xchat.command ("MENU ADD \"EasyXdcc/Stop\" \"xdcc stop\"") 534 | xchat.command ("MENU ADD \"EasyXdcc/Queue(s)\" \"xdcc queue\"") 535 | xchat.command ("MENU ADD \"EasyXdcc/Save\" \"xdcc save\"") 536 | xchat.command ("MENU ADD \"EasyXdcc/Load\" \"xdcc load\"") 537 | xchat.command ("MENU ADD \"EasyXdcc/Help\" \"xdcc help\"") 538 | 539 | if os.path.exists(sav_dir + "autostart"): 540 | xchat.command ("MENU -t1 ADD \"EasyXdcc/Auto-Start\" \"xdcc auto on\" \"xdcc auto off\"") 541 | else: 542 | xchat.command ("MENU -t0 ADD \"EasyXdcc/Auto-Start\" \"xdcc auto on\" \"xdcc auto off\"") 543 | 544 | print("Plugin EasyXdcc loaded!") 545 | 546 | xchat.command ("xdcc load") 547 | if len(queue.bots) > 0: 548 | xchat.command ("xdcc queue") 549 | if os.path.exists(sav_dir + "autostart"): 550 | xchat.command ("xdcc start") 551 | else: 552 | print("/XDCC START to start downloading!") 553 | 554 | print("/XDCC HELP for more") 555 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Bouliere Tristan & Dan Bennett 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of EasyXdcc nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EasyXdcc 2 | ======== 3 | 4 | XDCC download manager with support for simultaneous queues on different channels, servers and bots, as well as saving/loading queue state. 5 | 6 | __Current Version: 1.3__ ([changelog](#changelog)) 7 | 8 | __Current Home: [Ultrabenosaurus/EasyXdcc](https://github.com/Ultrabenosaurus/EasyXdcc)__ 9 | 10 | ## Credit 11 | 12 | This is not originally my work, I just found it and made some modifications. The site seems to be down even though the file is still accessible and searching for over an hour looking for an updated version returned nothing helpful, so I decided to host it here. 13 | 14 | The original is by Bouliere Tristan and can be found in the [XChat plugin repository](http://xchat.org/cgi-bin/search.pl?str=easyxdcc&cat=0&Submit=Search). I attempted to email Bouliere using the address given in the source code to tell him about this repo, but I got a bounceback saying it didn't exist. 15 | 16 | ## Install 17 | 18 | Simply copy `EasyXdcc.py` to your IRC client's plugins folder. Original version designed for XChat 2, my version is tested and working in HexChat 2.10.1. May or may not work in any other client. 19 | 20 | Confirm it is loaded and active in your client's plugin manager. 21 | 22 | :shipit: 23 | 24 | ## Usage 25 | 26 | Make sure you have joined a channel with access to the bot you want files from, then use one of the following commands: 27 | 28 | * `/XDCC ADD [bot_name] [n°_pack]` 29 | * `/XDCC ADDL [bot_name] [n°_pack_beg] [n°_pack_end]` 30 | * `/XDCC ADDM [bot_name] [n°_pack_1] [n°_pack_2] [...]` 31 | 32 | You can use `/XDCC QUEUE` or `/XDCC QUEUE [bot_name]` to view the current queue. 33 | 34 | If it doesn't start downloading stuff for you automatically enter `/XDCC START` to get things going. To make it start downloading automatically in the future, enter `/XDCC AUTO ON` or toggle it form the EasyXdcc menu option. 35 | 36 | The start/stop/auto-start and load/save/show queue functions are also available from a custom menu added to your client's interface. Additionally, the menu entry for auto-start will tell you whether the feature is currently on or off. 37 | 38 | ## All Commands 39 | 40 | ``` 41 | Queue a pack : 42 | /XDCC ADD [bot_name] [n°_pack] 43 | 44 | Queue a pack list : 45 | /XDCC ADDL [bot_name] [n°_pack_beg] [n°_pack_end] 46 | 47 | Queue non-sequential pack list : 48 | /XDCC ADDM [bot_name] [n°_pack_1] [n°_pack_2] [...] 49 | 50 | See pack queue : 51 | /XDCC QUEUE 52 | 53 | See pack queue for a bot : 54 | /XDCC QUEUE [bot_name] 55 | 56 | Withdraw a pack from queue : 57 | /XDCC RMP [bot_name] [n°pack] 58 | 59 | Withdraw a pack list from queue : 60 | /XDCC RMPL [bot_name] [n°pack_beg] [N°pack_end] 61 | 62 | Withdraw a non-sequential pack list from queue : 63 | /XDCC RMPM [bot_name] [n°_pack_1] [n°_pack_2] [...] 64 | 65 | Withdraw a bot from queue : 66 | /XDCC RMBOT [bot_name] 67 | 68 | Stop EasyXdcc : 69 | /XDCC STOP 70 | 71 | Start EasyXdcc : 72 | /XDCC START 73 | 74 | Show auto-start status : 75 | /XDCC AUTO 76 | 77 | Toggle auto-start : 78 | /XDCC AUTO [ON|OFF] 79 | 80 | Save Queue : 81 | /XDCC SAVE 82 | 83 | Load Queue : 84 | /XDCC LOAD 85 | 86 | Delete saved Queue file : 87 | /XDCC PURGE 88 | ``` 89 | 90 | ## TODO 91 | 92 | * use JSON for queue file 93 | * I hope python knows how to do JSON natively... 94 | * refactor for latest HexChat python interface guidelines 95 | * handle both XChat and HexChat interfaces or just go with HexChat now? 96 | * make it smarter 97 | * file transfer status 98 | * automatic retry of failed transfers 99 | 100 | ## Changelog 101 | 102 | ### 1.3 103 | 104 | * auto-start feature 105 | * help text 106 | * menu item 107 | * handle loss of connection 108 | * fix queue deletion to include in-memory queue 109 | 110 | ### 1.2 111 | 112 | * auto-load queue file when plugin loads 113 | * OS detection for paths 114 | * create paths if they don't exist 115 | 116 | ### 1.1 117 | 118 | * normalise indentation 119 | * non-sequential pack list add/remove 120 | * queue deletion 121 | * menu entry for help text 122 | * Windows path for queue file 123 | -------------------------------------------------------------------------------- /osdircheck.py: -------------------------------------------------------------------------------- 1 | import os, pprint, platform; 2 | 3 | def check_dirs(f): 4 | d = os.path.dirname(f) 5 | if not os.path.exists(d): 6 | os.makedirs(d) 7 | 8 | comp = platform.system() 9 | user = "ghost" 10 | 11 | print comp 12 | 13 | try: 14 | cmd = os.popen("whoami") 15 | try: 16 | user = cmd.readlines() 17 | user = user[0].strip("\n") 18 | if 'Windows' == comp: 19 | user = user.split("\\")[1] 20 | finally: 21 | cmd.close() 22 | except IOError: 23 | print "Error: can't use CMD" 24 | print user 25 | 26 | if 'Windows' == comp: 27 | sav_dir = "C:/Users/"+user+"/.config/EasyXdcc/" 28 | else: 29 | sav_dir = "/home/"+user+"/.config/EasyXdcc/" 30 | check_dirs(sav_dir) 31 | sav_file = sav_dir + "queue" 32 | 33 | try: 34 | file = open(sav_file,'rb') 35 | try: 36 | for line in file.readlines(): 37 | print line 38 | finally: 39 | file.close() 40 | except IOError: 41 | print "Error: can\'t find file or read data" 42 | -------------------------------------------------------------------------------- /testplugin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | __module_name__ = "tester" 3 | __module_version__ = "x.x" 4 | __module_description__ = "plugin for testing random shit" 5 | __module_author__ = "Ultrabenosaurus " 6 | import hexchat, os, time, pprint, platform 7 | 8 | def main(word, word_eol, userdata): 9 | argc = len(word) 10 | 11 | if argc == 3: 12 | if("info" == word[1]): 13 | print word[1] + ": " + hexchat.get_info(word[2]) 14 | else: 15 | print "tester: use a proper command" 16 | 17 | return hexchat.EAT_ALL 18 | 19 | hexchat.hook_command("tester", main, help="/tester ") 20 | --------------------------------------------------------------------------------