├── PerformPostBatch.class ├── menu.json ├── config.xml ├── PerformPostBatch.java ├── README └── sync_dir_collection.sh /PerformPostBatch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/collectionSync/master/PerformPostBatch.class -------------------------------------------------------------------------------- /menu.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | {"name": "Generate collections", "priority": 1, "action": "sync_dir_collection.sh"} 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | collectionSync 5 | 1.0 6 | Fuxin Zhang 7 | collectionSync 8 | 9 | 10 | menu.json 11 | 12 | 13 | -------------------------------------------------------------------------------- /PerformPostBatch.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.net.*; 3 | 4 | /** a simple class that connects to kindle touch's http://localhost:9101/change, 5 | then use post method to put a series of commands in file ./commands to update collections 6 | */ 7 | public class PerformPostBatch { 8 | public static void main(String[] argv) throws Exception { 9 | URL url = new URL("http://localhost:9101/change"); 10 | 11 | boolean abnormal = false; 12 | String line,line_in; 13 | BufferedReader f 14 | = new BufferedReader(new FileReader("./commands")); 15 | 16 | BufferedReader in; 17 | 18 | 19 | while ((line = f.readLine()) != null) { 20 | //System.out.println(line); 21 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 22 | connection.setRequestMethod("POST"); 23 | connection.setDoOutput(true); 24 | PrintWriter out = new PrintWriter(connection.getOutputStream()); 25 | 26 | out.println(line); 27 | out.close(); 28 | 29 | in = new BufferedReader(new InputStreamReader(connection.getInputStream())); 30 | 31 | while ((line_in = in.readLine()) != null) { 32 | System.out.print(line_in); 33 | if (!line_in.startsWith("{\"ok\":true")) { 34 | System.out.println("Wrong response!"); 35 | abnormal = true; 36 | } 37 | } 38 | in.close(); 39 | } 40 | if (abnormal) throw new Exception(); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This extension requires yifanlu's guilauncher to work. It is only tested a 2 | bit with https://github.com/downloads/yifanlu/KindleLauncher/kindle_launcher_1.0.zip. 3 | Use at your own risk. 4 | 5 | unrar this package, copy the whole collectionSync directory into kindle drive's 6 | extentsions/ directory(available only after you install the launcher). Reboot. 7 | You should see a new menu in launcher->"generate collections". 8 | 9 | Be careful!! Any existing collections will be deleted, new collections with be 10 | created according to currrent contents on the drive: 11 | a/b.txt 12 | a/c/d.txt 13 | a/c/e.txt 14 | => a(1) 15 | a-c(2) 16 | 17 | The process might be quite slow if you have lots of books. To let you know a bit 18 | about the progress, the plugin will first put kindle into screensaver mode until 19 | it finish generate all necessary commands(/mnt/us/extensions/collectionSync/commands 20 | file), then start to perform the real work(delete/insert/update collections, you can 21 | see my items and page numbers changing in this phase), at last it will enter screensaver 22 | mode again to tell you all work is done. 23 | 24 | Known limits: 25 | 1, It uses Chinese character '-' to seperate directory hierarchy, if your directories 26 | contains such character, generation will (partly) fail. 27 | 2012/3/29 update: This is removed now, we will wait for the scanner to do its job(2, 28 | Kindle is slow at scanning books. After copying lots of books onto it, you should wait 29 | enough time for it to finish the generation of entries database items. Otherwise the 30 | script might fail due to database operation conflicts with system.) 31 | 32 | Happy Hacking. 33 | 34 | In Chinese: 35 | 36 | 这个扩展依赖于yifanlu的guilauncher插件,先安装https://github.com/downloads/yifanlu/ 37 | KindleLauncher/kindle_launcher_1.0.zip,然后把本安装包解压后得到的collectSync目录 38 | 拷贝到kindle盘extensions目录下,重启,就会看到menu-launcher菜单下有新的选项"generate 39 | collections",选中后就会根据您的kindle目录下的内容生成分类。 40 | 41 | 这个扩展本质上是一个hack,作者对可能的风险不作任何担保。 42 | 43 | 生成分类的过程大致如下:根据documents目录下的内容,只要某个目录下有文件,就会生成相应分类, 44 | 分类名由目录名生成,例如: 45 | a/b.txt 46 | a/c/d.txt 47 | a/c/e.txt 48 | 会生成: 49 | a(1) //分类a下有一个文件 50 | a-c(2) //分类a-c下有两个文件 51 | 52 | 如果有很多书,这个过程可能会很慢。为了多少给点进度提示,它会先进入屏保,在完成了命令文件 53 | (/mnt/us/extensions/collectionSync/commands)的生成之后,关闭屏保,再进行实际的工作( 54 | 即commands文件的删除分类、插入分类、更新分类内容的命令,这个过程你在首页会看到my items的 55 | 数量和page的数量在变化,一般是先增加再减少),所有工作完成后再次进入屏保。 56 | 57 | 如果开始工作的时候kindle还没有完成扫描书目,它会等待,每三秒换一下屏保,以提示还在工作。 58 | 59 | 2012/3/29: 为了方便查看问题,增加了一些调试信息输出,如果有任何问题,可以查看 60 | extensions/collectionSync/目录的commands和log文件, commands是json命令,log是调试信息 61 | 如果成功,log的输出应该类似: 62 | Started at Thu Mar 29 15:53:29 UTC 2012 63 | Successfully done. 64 | 65 | 如果开始的时候要等scanner,则类似这样: 66 | Kindle scanner has not finished scanned all books, Waiting start at date Thu Mar 29 15:54:24 UTC 2012 67 | w Int doFullScan 68 | rw Str logMask [0xffff0000] 69 | rw Str logLevel [Current log level=info 70 | (Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)] 71 | r Int fullScanStatus [5] 72 | Started at Thu Mar 29 15:54:39 UTC 2012 73 | Successfully done. 74 | 75 | 如果有些书格式kindle不认识,还会有一些warning信息。 76 | 77 | 如果由于某种原因失败了,会把系统的调试信息dump在log文件里。 78 | 79 | 已知限制: 80 | 1, 扩展用中文的"-"字符来分割目录层次,如果目录中有这个字符会导致生成失败。 81 | 2012/3/29, 这个应该已经修复了。(2, 扩展依赖于kindle自身的文件扫描和数据库操作接口,在导 82 | 入大量书的时候,应该给kindle足够的时间扫描书目,完成基本的数据库操作,否则在生成分类时扩展 83 | 的数据库操作和系统的数据库操作可能冲突,导致超时失败。) 84 | 85 | Fuxin Zhang 86 | 2012/3/29 87 | -------------------------------------------------------------------------------- /sync_dir_collection.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### This script tries to create collections from documents directory, it will erase any existing collections 4 | ### Use at your own risk. Fuxin Zhang 5 | clear_existing_collections() { 6 | delete_post_prefix='{"commands":[{"delete":{"uuid":"' 7 | delete_post_suffix='"}}],"type":"ChangeRequest","id":1}' 8 | sql="select p_uuid from Entries where p_type== 'Collection'"; 9 | sqlite3 /var/local/cc.db "$sql" | while read u; do 10 | post_data=$delete_post_prefix$u$delete_post_suffix 11 | # echo "Deleting collection $u" $post_data 12 | echo $post_data >> ./commands 13 | # /usr/java/bin/cvm PerformPost change $post_data 14 | done 15 | } 16 | 17 | insert_collection() { 18 | insert_post_data_prefix='{"commands":[{"insert":{"type":"Collection","uuid":"'; 19 | insert_post_data_1='","lastAccess":'; 20 | insert_post_data_2=',"titles":[{"display":"'; 21 | insert_post_data_3='","direction":"LTR","language":"en-US"}],"isVisibleInHome":true}}],"type":"ChangeRequest","id":2}'; 22 | 23 | # echo "inserting collection" $1 24 | uuid=`cat /proc/sys/kernel/random/uuid` 25 | post_data=$insert_post_data_prefix$uuid$insert_post_data_1`date +%s`$insert_post_data_2$1$insert_post_data_3; 26 | echo $post_data >> ./commands 27 | # /usr/java/bin/cvm PerformPost change $post_data 28 | } 29 | 30 | update_collection() { 31 | update_post_data_prefix='{"commands":[{"update":{"type":"Collection","uuid":"' 32 | update_post_data_1='","members":[' 33 | update_post_data_2=']}}],"type":"ChangeRequest","id":7}' 34 | # echo "updating members for collection " $1 $2 35 | 36 | dir="/mnt/us/documents/"`echo "$1" | sed 's/-/\//g'` 37 | 38 | ##be careful for file name with spaces! 39 | post_data=$update_post_data_prefix$2$update_post_data_1 40 | n=0 41 | find "$dir" -maxdepth 1 -type f | while read f ; do 42 | sql="select p_uuid from Entries where p_location == '"$f"'"; 43 | u=`sqlite3 /var/local/cc.db "$sql"`; 44 | if test $u; then 45 | ##echo "add uuid $u" 46 | n=$((n+1)) 47 | if [ $n -gt 1 ] ; then 48 | member_data=$member_data\,\"$u\" 49 | else 50 | member_data=\"$u\" 51 | fi 52 | else 53 | echo "Warning:$f is not in the Entries database, will be ignored!" >> ./log 54 | echo "Warning:Either it is not in a format recognized by kindle, or you have not waited kindle to finish the scan? If so retry later." >> ./log 55 | fi 56 | echo $member_data > /tmp/member_data 57 | done 58 | post_data=$post_data`cat /tmp/member_data`$update_post_data_2 59 | # echo "updating collection" $1 $post_data 60 | echo $post_data >> ./commands 61 | # /usr/java/bin/cvm PerformPost change $post_data 62 | } 63 | 64 | create_collections() { 65 | 66 | ##find all dirs, remove prefix /mnt/us/documents/, replace '/' to '-', filter out .sdr files(used by kindle), empty lines, and /mnt/us/documents itself 67 | find /mnt/us/documents -type d | sed "s/^\/mnt\/us\/documents\///g" | sed "s/\//-/g" | grep -v "\.sdr$" | \ 68 | grep -v "^$" | grep -v "-mnt-us-documents" | while read dir; do 69 | 70 | realdir="/mnt/us/documents/"`echo "$dir" | sed 's/-/\//g'` 71 | filecount=`find "$realdir" -maxdepth 1 -type f | wc -l` 72 | 73 | ##echo $dir,$realdir,$filecount 74 | if [ $filecount -gt 0 ] ; then 75 | insert_collection "$dir" 76 | update_collection "$dir" $uuid 77 | fi 78 | done 79 | } 80 | 81 | cd /mnt/us/extensions/collectionSync 82 | rm -f ./commands 83 | rm -f ./log 84 | touch ./commands 85 | 86 | ### enter screensaver mode to tell user work start 87 | lipc-set-prop com.lab126.powerd preventScreenSaver 0 88 | lipc-set-prop com.lab126.powerd powerButton 1 89 | lipc-set-prop com.lab126.powerd preventScreenSaver 1 90 | 91 | scan_done=`lipc-get-prop com.lab126.scanner fullScanStatus` 92 | if [ $scan_done -ne 0 ] ; then 93 | echo "Kindle scanner has not finished scanned all books, Waiting start at date" `date` >> ./log 94 | lipc-probe -v com.lab126.scanner >> ./log 95 | fi 96 | times=0 97 | while [ $scan_done -ne 0 ] ; do 98 | scan_done=`lipc-get-prop com.lab126.scanner fullScanStatus` 99 | sleep 3 100 | lipc-set-prop com.lab126.powerd preventScreenSaver 0 101 | lipc-set-prop com.lab126.powerd powerButton 1 102 | lipc-set-prop com.lab126.powerd preventScreenSaver 1 103 | times=$((times+1)) 104 | if [ $times -gt 1000 ] ; then 105 | echo "Wait for too long a time, quit..." >> ./log 106 | fi 107 | done 108 | echo "Started at " `date` >> ./log 109 | 110 | ### pause indexer 111 | lipc-set-prop com.lab126.indexer pauseIndexerMilliseconds 6000000 112 | sleep 1 113 | 114 | ### first of all, delete all existing collections 115 | clear_existing_collections 116 | 117 | ### then find out all directories that have >=1 regular files 118 | ### create a collection and fill in items 119 | create_collections 120 | 121 | lipc-set-prop com.lab126.powerd preventScreenSaver 0 122 | lipc-set-prop com.lab126.powerd powerButton 1 123 | lipc-set-prop com.lab126.powerd preventScreenSaver 1 124 | 125 | /usr/java/bin/cvm PerformPostBatch 126 | if [ $? -ne 0 ]; then 127 | echo "Something goes wrong, dump the log" 128 | showlog >> ./log 129 | else 130 | echo "Successfully done." >> ./log 131 | fi 132 | #rm -f ./commands 133 | 134 | ### let indexer continue 135 | lipc-set-prop com.lab126.indexer pauseIndexerMilliseconds 0 136 | 137 | ### enter screensaver mode to tell user work done 138 | lipc-set-prop com.lab126.powerd preventScreenSaver 0 139 | lipc-set-prop com.lab126.powerd powerButton 1 140 | --------------------------------------------------------------------------------