├── requirements.txt ├── README.md ├── encryption.js ├── 115links.txt ├── fake115upload.py └── fake115upload.user.js /requirements.txt: -------------------------------------------------------------------------------- 1 | hexdump==3.3 2 | ecdsa==0.16.0 3 | lz4==2.2.1 4 | requests_toolbelt==0.9.1 5 | requests==2.22.0 6 | pycryptodome==3.9.8 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # For Research Purposes Only 3 | # Usage: 4 | 5 | ``` 6 | -c cid : Folder cid 7 | -u filename: Upload a file form local disk 8 | -i filename: Import files form hashlink list 9 | -o filename: Export file hashlink from 115 10 | -b filename: Build file hashlink from local disk 11 | ``` 12 | 13 | -------------------------------------------------------------------------------- /encryption.js: -------------------------------------------------------------------------------- 1 | //Create by T3rry 2 | 3 | var forge = require('node-forge'); 4 | var urlencode = require('urlencode'); 5 | var http = require('http'); 6 | 7 | var pub_key='-----BEGIN PUBLIC KEY-----\ 8 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR3rWmeYnRClwLBB0Rq0dlm8Mr\ 9 | PmWpL5I23SzCFAoNpJX6Dn74dfb6y02YH15eO6XmeBHdc7ekEFJUIi+swganTokR\ 10 | IVRRr/z16/3oh7ya22dcAqg191y+d6YDr4IGg/Q5587UKJMj35yQVXaeFXmLlFPo\ 11 | kFiz4uPxhrB7BGqZbQIDAQAB\ 12 | -----END PUBLIC KEY-----' 13 | 14 | var private_key='-----BEGIN RSA PRIVATE KEY-----\ 15 | MIICXAIBAAKBgQCMgUJLwWb0kYdW6feyLvqgNHmwgeYYlocst8UckQ1+waTOKHFC\ 16 | TVyRSb1eCKJZWaGa08mB5lEu/asruNo/HjFcKUvRF6n7nYzo5jO0li4IfGKdxso6\ 17 | FJIUtAke8rA2PLOubH7nAjd/BV7TzZP2w0IlanZVS76n8gNDe75l8tonQQIDAQAB\ 18 | AoGANwTasA2Awl5GT/t4WhbZX2iNClgjgRdYwWMI1aHbVfqADZZ6m0rt55qng63/\ 19 | 3NsjVByAuNQ2kB8XKxzMoZCyJNvnd78YuW3Zowqs6HgDUHk6T5CmRad0fvaVYi6t\ 20 | viOkxtiPIuh4QrQ7NUhsLRtbH6d9s1KLCRDKhO23pGr9vtECQQDpjKYssF+kq9iy\ 21 | A9WvXRjbY9+ca27YfarD9WVzWS2rFg8MsCbvCo9ebXcmju44QhCghQFIVXuebQ7Q\ 22 | pydvqF0lAkEAmgLnib1XonYOxjVJM2jqy5zEGe6vzg8aSwKCYec14iiJKmEYcP4z\ 23 | DSRms43hnQsp8M2ynjnsYCjyiegg+AZ87QJANuwwmAnSNDOFfjeQpPDLy6wtBeft\ 24 | 5VOIORUYiovKRZWmbGFwhn6BQL+VaafrNaezqUweBRi1PYiAF2l3yLZbUQJAf/nN\ 25 | 4Hz/pzYmzLlWnGugP5WCtnHKkJWoKZBqO2RfOBCq+hY4sxvn3BHVbXqGcXLnZPvo\ 26 | YuaK7tTXxZSoYLEzeQJBAL8Mt3AkF1Gci5HOug6jT4s4Z+qDDrUXo9BlTwSWP90v\ 27 | wlHF+mkTJpKd5Wacef0vV+xumqNorvLpIXWKwxNaoHM=\ 28 | -----END RSA PRIVATE KEY-----' 29 | 30 | var rsa = forge.pki.rsa; 31 | const priv = forge.pki.privateKeyFromPem(private_key); 32 | const pub = forge.pki.publicKeyFromPem(pub_key); 33 | const g_key_l=[0x42,0xda,0x13,0xba,0x78,0x76,0x8d,0x37,0xe8,0xee,0x04,0x91] 34 | const g_key_s=[0x29,0x23,0x21,0x5e] 35 | const g_kts=[0xf0,0xe5,0x69,0xae,0xbf,0xdc,0xbf,0x5a,0x1a,0x45,0xe8,0xbe,0x7d,0xa6,0x73,0x88,0xde,0x8f,0xe7,0xc4,0x45,0xda,0x86,0x94,0x9b,0x69,0x92,0x0b,0x6a,0xb8,0xf1,0x7a,0x38,0x06,0x3c,0x95,0x26,0x6d,0x2c,0x56,0x00,0x70,0x56,0x9c,0x36,0x38,0x62,0x76,0x2f,0x9b,0x5f,0x0f,0xf2,0xfe,0xfd,0x2d,0x70,0x9c,0x86,0x44,0x8f,0x3d,0x14,0x27,0x71,0x93,0x8a,0xe4,0x0e,0xc1,0x48,0xae,0xdc,0x34,0x7f,0xcf,0xfe,0xb2,0x7f,0xf6,0x55,0x9a,0x46,0xc8,0xeb,0x37,0x77,0xa4,0xe0,0x6b,0x72,0x93,0x7e,0x51,0xcb,0xf1,0x37,0xef,0xad,0x2a,0xde,0xee,0xf9,0xc9,0x39,0x6b,0x32,0xa1,0xba,0x35,0xb1,0xb8,0xbe,0xda,0x78,0x73,0xf8,0x20,0xd5,0x27,0x04,0x5a,0x6f,0xfd,0x5e,0x72,0x39,0xcf,0x3b,0x9c,0x2b,0x57,0x5c,0xf9,0x7c,0x4b,0x7b,0xd2,0x12,0x66,0xcc,0x77,0x09,0xa6] 36 | 37 | m115_l_rnd_key=[] 38 | m115_s_rnd_key=[] 39 | key_s=[] 40 | key_l=[] 41 | 42 | function intToByte(i) { 43 | var b = i & 0xFF; 44 | var c = 0; 45 | if (b >= 256) { 46 | c = b % 256; 47 | c = -1 * (256 - c); 48 | } else { 49 | c = b; 50 | } 51 | 52 | return c 53 | 54 | } 55 | 56 | function stringToArray(s) { 57 | 58 | var map = Array.prototype.map 59 | 60 | var array = map.call(s,function(x){ 61 | return x.charCodeAt(0); 62 | 63 | }) 64 | 65 | return array 66 | } 67 | 68 | function arrayTostring(array){ 69 | var result = ""; 70 | for(var i = 0; i < array.length; ++i){ 71 | result+= (String.fromCharCode(array[i])); 72 | } 73 | return result; 74 | } 75 | 76 | function m115_init() 77 | { 78 | m115_l_rnd_key=[] 79 | m115_s_rnd_key=[] 80 | key_s=[] 81 | key_l=[] 82 | } 83 | 84 | function m115_setkey(randkey,sk_len) 85 | { 86 | var length=sk_len *(sk_len-1) 87 | var index=0 88 | var xorkey='' 89 | 90 | if (randkey) 91 | { 92 | for (var i = 0; i 0){ 119 | 120 | for (var i = 0; i =lkey){ 129 | num=num%lkey 130 | } 131 | 132 | secret.push((src[i]^key[num])) 133 | num+=1 134 | } 135 | 136 | return secret 137 | 138 | 139 | } 140 | function genRandom(len) 141 | { 142 | 143 | var keys=[] 144 | var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz23456789'; 145 |  var maxPos = chars.length; 146 |    147 |  for (i = 0; i < len; i++) { 148 |     keys.push(chars.charAt(Math.floor(Math.random() * maxPos)).charCodeAt(0)); 149 |   } 150 |   return keys; 151 | } 152 | function m115_encode(plaintext) 153 | 154 | { 155 | console.log('m115_encode:') 156 | 157 | m115_init() 158 | 159 | key_l=g_key_l 160 | 161 | m115_l_rnd_key=genRandom(16) 162 | 163 | m115_setkey(m115_l_rnd_key,4) 164 | 165 | var tmp=xor115_enc(stringToArray(plaintext),key_s).reverse() 166 | 167 | var xortext= xor115_enc(tmp,key_l) 168 | 169 | var text=arrayTostring(m115_l_rnd_key)+arrayTostring(xortext) 170 | 171 | var ciphertext =pub.encrypt(text) 172 | 173 | ciphertext=urlencode(forge.util.encode64(ciphertext)) 174 | 175 | return ciphertext 176 | 177 | } 178 | 179 | function m115_decode(ciphertext) 180 | { 181 | console.log('m115_decode:') 182 | var bciphertext=forge.util.decode64(ciphertext) 183 | var block=bciphertext.length/(128) 184 | var plaintext ='' 185 | 186 | var index=0 187 | 188 | for (var i = 1; i <=block; ++i) { 189 | plaintext+=priv.decrypt(bciphertext.slice(index, i*128)) 190 | index+=128 191 | } 192 | 193 | m115_s_rnd_key =stringToArray(plaintext.slice(0,16)) 194 | 195 | plaintext=plaintext.slice(16); 196 | 197 | m115_setkey(m115_l_rnd_key,4) 198 | 199 | m115_setkey(m115_s_rnd_key,12) 200 | 201 | tmp=xor115_enc(stringToArray(plaintext),key_l).reverse() 202 | 203 | plaintext=xor115_enc(tmp,key_s) 204 | 205 | return arrayTostring(plaintext) 206 | } 207 | 208 | function CreateDownloadTask(pc) 209 | { 210 | 211 | var post_data = 'data='+m115_encode('{"pickcode":'+pc+'}') 212 | var options = { 213 | host: 'proapi.115.com', 214 | port: 80, 215 | path: '/app/chrome/downurl', 216 | method: 'post', 217 | headers: { 218 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 115Browser/23.9.2', 219 | 'Content-Type':'application/x-www-form-urlencoded', 220 | 'Content-Length':post_data.length, 221 | 'Cookie': 'xxxxxxxxxxxxxxxxxxxxxxxxx' 222 | }}; 223 | 224 | var post_req = http.request(options, function(res) { 225 | res.setEncoding('utf8'); 226 | res.on('data', function (chunk) { 227 | var bodyString = JSON.parse(chunk)['data']; 228 | resp=m115_decode(bodyString) 229 | console.log(JSON.parse(resp)) 230 | }); 231 | }); 232 | 233 | post_req.write(post_data); 234 | post_req.end(); 235 | 236 | } 237 | 238 | CreateDownloadTask('xxxxxxxxxxxxxxx') 239 | -------------------------------------------------------------------------------- /115links.txt: -------------------------------------------------------------------------------- 1 | Slam.Dunk.E06.2013.720p.HDTV.x264.AAC-NGB.mkv|241592994|0DD796DEB61E03EFD59EAA0FA2CEAC2941A88946|381BBCFF26ABE2DE4DB2E76E2E69865D33AACDFA 2 | Slam.Dunk.E52.2013.720p.HDTV.x264.AAC-NGB.mkv|286267660|2669FA5B6BF252ADC52DC7673E58451349567AD6|134C6442DB195A50288752A1F5076B704A943A8A 3 | Slam.Dunk.E17.2013.720p.HDTV.x264.AAC-NGB.mkv|322620610|C044B3E48D760E2BBC8500E687EDCE30E63D3EAE|4736043BA45EF3402E209DA505FB278D22B9B2AE 4 | Slam.Dunk.E03.2013.720p.HDTV.x264.AAC-NGB.mkv|231754327|377873C374560DDEEBDFDD45AAF831B62578D69B|CF4A8F2F557BED31E73BDE7779300F4D3A06774B 5 | Slam.Dunk.E20.2013.720p.HDTV.x264.AAC-NGB.mkv|322832098|0679BE1E5E865E2F10D3D47D810E8789545F782D|FD12223A49575F23B9BAA391E300B4AE00CA8695 6 | Slam.Dunk.E54.2013.720p.HDTV.x264.AAC-NGB.mkv|285172644|CB681D8F1B0E9BE0DA83874578AF780AD7C7E009|555EB90F8AAF458540C474CB49B1B58F97077349 7 | Slam.Dunk.E29.2013.720p.HDTV.x264.AAC-NGB.mkv|284803396|C3339FDB57412823F8E2B8C6EE530F4D595372FA|CE0D4DE242AFE1C598E17EF519690F94542EE740 8 | Slam.Dunk.E63.2013.720p.HDTV.x264.AAC-NGB.mkv|290456922|59CC1ED202F68402F766D215CD4F2C2EAB367C3A|51A0B749EF03065A4A1338C8DC79A754728583B9 9 | Slam.Dunk.E22.2013.720p.HDTV.x264.AAC-NGB.mkv|320903706|56281E502216275603288D2CE557A633A2D208A0|A006DDD8C2B21B48A7D3E486C13B0392CA1791DE 10 | Slam.Dunk.E78.2013.720p.HDTV.x264.AAC-NGB.mkv|281907389|AE70A5C7C168E0E11603C48165FD48955EC79DB3|C8E86EB71758A4F7B61E458B494C1EDE5F815F63 11 | Slam.Dunk.E77.2013.720p.HDTV.x264.AAC-NGB.mkv|282595597|959B8DF4B4280FED1ABD514A764E259838D9DD94|23707058F446970BCF95484DE7970C0C49A3ABDE 12 | Slam.Dunk.E82.2013.720p.HDTV.x264.AAC-NGB.mkv|282853031|0453B89E5DF6F11D59FB5352DDF75ECED1E63AFA|66BA425819565E260DCC5F2A3C3D83FD1650F4C0 13 | Slam.Dunk.E68.2013.720p.HDTV.x264.AAC-NGB.mkv|282934483|D26A48CDD7E6582267100F280C5EB2D8CBAFF7D9|21AC07A8B336A8403913C7AA24919E7EE57F7FD0 14 | Slam.Dunk.E11.2013.720p.HDTV.x264.AAC-NGB.mkv|321386656|3FA1CA0962A3F67D7B18FCB60D1168A5D28A179A|1F47E7E64A123C9615E524D2C8D5AF44F832F5D5 15 | Slam.Dunk.E97.2013.720p.HDTV.x264.AAC-NGB.mkv|264386183|FA7E021581B5BE8F14314DB7D72809503A741639|C26A4BDF9B6B5EC887DDEFDDD2CD93E6A530C51E 16 | Slam.Dunk.E75.2013.720p.HDTV.x264.AAC-NGB.mkv|282649452|61AA97F32773B1060267EECED8078F9B2E856CC1|1F317735898DED85810CA9B3DBFE01F6D85572BC 17 | Slam.Dunk.E96.2013.720p.HDTV.x264.AAC-NGB.mkv|264293585|85D3379EDA058ABE10ABC5E9212510A5DB144E12|452D84A16D3EE2185851C67D92E330B2D05DB896 18 | Slam.Dunk.E28.2013.720p.HDTV.x264.AAC-NGB.mkv|283870720|6F7F9A401045A68AC3877BE7101E596EE1482308|9D981AF3EDD4FE8470E89197778319EB1B954876 19 | Slam.Dunk.E99.2013.720p.HDTV.x264.AAC-NGB.mkv|264282879|5E4E95BE7D1656CF9DC99762BB5DB61221F5042D|1A8B22573E23A51F5F38993423679C7643776B9F 20 | Slam.Dunk.E94.2013.720p.HDTV.x264.AAC-NGB.mkv|264270731|EFE33ADAC264D6DEC378C054FF6A7176B66F6C91|D776EC877694BFE057E042CCC2EF2E8AA5FD7B16 21 | Slam.Dunk.E60.2013.720p.HDTV.x264.AAC-NGB.mkv|293733122|B4775F81AABD7A4AF8A73D9CE831C2F6D2E52D71|779F1585E2AC9005E0A2F7D0A1B77B90DB50A4BA 22 | Slam.Dunk.E10.2013.720p.HDTV.x264.AAC-NGB.mkv|321111164|5BC503577B17AE2CA06331711E34ED2CC32FD0E0|CD00D4021C658C93C849CA3D4C69C1DBC1D423A2 23 | Slam.Dunk.E49.2013.720p.HDTV.x264.AAC-NGB.mkv|287073292|6A04E2D02A0202CE5AFE41829F89D2FBBA6B7A66|0848774C240CD4719BF1BF3754F52EF39901923A 24 | Slam.Dunk.E81.2013.720p.HDTV.x264.AAC-NGB.mkv|281959543|04828A00BCCA1296063A23918D98B9E843313321|288DA7D95B435DCF7510099CF4BDD8F033DEE709 25 | Slam.Dunk.E13.2013.720p.HDTV.x264.AAC-NGB.mkv|319699111|028D842A88F4576784FFFFEA871AD1BD9E1047CA|6367C48334A55A146DCAF1483E6CC248ACCB61C9 26 | Slam.Dunk.E86.2013.720p.HDTV.x264.AAC-NGB.mkv|264150644|6684CD350D10BC610F5486399687A098C2F8461B|568ADF0FEDFEC6A6F814FA24D8E5E248660592DC 27 | Slam.Dunk.E42.2013.720p.HDTV.x264.AAC-NGB.mkv|285482460|25C475D06365AA58C52DA423A79FF1D689A33834|8509794F1B15C5E9F81E59CA6D7E88291FEF47D8 28 | Slam.Dunk.E87.2013.720p.HDTV.x264.AAC-NGB.mkv|264080492|3B380A8B518E29951E82C69C28652C17480D3E52|5442E4DEEF5850A7DC20579E8BC512F02BA03CE2 29 | Slam.Dunk.E57.2013.720p.HDTV.x264.AAC-NGB.mkv|292020638|46D9A4C0724FEBF4D1CBE07139C1B22CAA7428CD|315A6F4F04C56D0CCEBB8378B64C7E2AC936ED18 30 | Slam.Dunk.E61.2013.720p.HDTV.x264.AAC-NGB.mkv|292483066|83368A035E62D7C59A5B2985A7301F1A2D0165DD|8AFF1EC85CD091F79E8F013F71B13C69E6D41807 31 | Slam.Dunk.E73.2013.720p.HDTV.x264.AAC-NGB.mkv|283323408|4EFC1F4E8A7BBADBBCBFFCABA5DA70B30DAC2FF9|C57C5990ABEA6C7BC5DA05C273EFB451091EDA43 32 | Slam.Dunk.E47.2013.720p.HDTV.x264.AAC-NGB.mkv|285946166|9A3D862E4FF94E24E6A1763C288E5F80EDF3485E|CE9F856A02C3123B220DC1ED759DA8F10A970638 33 | Slam.Dunk.E27.2013.720p.HDTV.x264.AAC-NGB.mkv|284784008|BCD608E911F9F8A63BDB66E0F059EDA9D5D3FC06|DFDD789D2820FDA989AC2E35647A6A5091D63A4D 34 | Slam.Dunk.E16.2013.720p.HDTV.x264.AAC-NGB.mkv|319514128|C2FE347FEF6C83F9390D98B027453AF2BAFDA659|6856A9FBCCC4BD6DA086AA2A18599079BAC8CB32 35 | Slam.Dunk.E48.2013.720p.HDTV.x264.AAC-NGB.mkv|287194303|65B82CEE80228AF317439A756A662FFFD2C1658D|A768DE45CFC8D67549ACAF6ACE5EEB39EC19290F 36 | Slam.Dunk.E02.2013.720p.HDTV.x264.AAC-NGB.mkv|232066070|38E0C3F81912964225A9D16B7172BE4DF2D83012|51F3128AADECA2E5DD3AC54A5A0A5F47F83375B8 37 | Slam.Dunk.E35.2013.720p.HDTV.x264.AAC-NGB.mkv|285590556|279E8757E176D8CFD3EBCA97254C3B91CF8E428D|6D86AA719D3E00CE43CC1D0DE08DE447C40A6DE0 38 | Slam.Dunk.E46.2013.720p.HDTV.x264.AAC-NGB.mkv|285222564|4E0D7FF2D0E78284956832C1B8F9B3989CEAAA0D|A4A65A7E59273A339ECDD80E6BAB661F99CB6EB4 39 | Slam.Dunk.E40.2013.720p.HDTV.x264.AAC-NGB.mkv|286291872|56A14157BF985845420C8AB69CB66738D300928B|7CC311E1B84DB90270F08AB1B04E43AD21D568EF 40 | Slam.Dunk.E62.2013.720p.HDTV.x264.AAC-NGB.mkv|292732135|F6593A3790BC53D2065226805733FAFF562F5CCA|081B8D25D9A875F3EAACADEAAF3179E25FE39785 41 | Slam.Dunk.E08.2013.720p.HDTV.x264.AAC-NGB.mkv|242487741|AD4E2B04A0653F96117F62055867B7E734D84054|1958D71BD1764A365FF6C0453CF1455DB231CF52 42 | Slam.Dunk.E79.2013.720p.HDTV.x264.AAC-NGB.mkv|281817192|A5D6C8EF3BC0701D225EB4010244087F5DCDAA3D|AA5B31FC94B90F7B6883A6BDC52C949D3388098C 43 | Slam.Dunk.E83.2013.720p.HDTV.x264.AAC-NGB.mkv|282788402|85F0AF99DD06FFDF86700857AF3C8A7C067E31E4|313424D2FD20F8F919E99A2D4D748B999116C627 44 | Slam.Dunk.E98.2013.720p.HDTV.x264.AAC-NGB.mkv|264376680|E0C32CCE6A26F203D857FF532606F3FD4FF6284B|1F2C0AB2A9000A9E18757B145427081F0F1C1E58 45 | Slam.Dunk.E92.2013.720p.HDTV.x264.AAC-NGB.mkv|264271785|3A0F5F180F3D0010C591C893386FD1DF10331431|370EDD17978CAADF86CCF9230E9655BEA6682A2B 46 | Slam.Dunk.E85.2013.720p.HDTV.x264.AAC-NGB.mkv|264208893|FAFFDFB8AE73DFB3219F0C01FED9B077D813B266|372BA1CAE0D2644812F589D54DE36A9F379868F4 47 | Slam.Dunk.E100.2013.720p.HDTV.x264.AAC-NGB.mkv|264270729|74373F512BC05DB8941EA0AB149AE87A199D8984|20D3571EE4D47AA40A3CEC524A25E466A0C96F12 48 | Slam.Dunk.E19.2013.720p.HDTV.x264.AAC-NGB.mkv|321773551|00237F510056F5655DBB6D030671717E01F66838|7770CDD16C08FE939A79727B2737F3E5961EEDAA 49 | Slam.Dunk.E76.2013.720p.HDTV.x264.AAC-NGB.mkv|282497225|49EDFEBCAD75DFE8C0BF77727BAAB9CA682B037A|0391B3B7301897EEBF2128B1F11443BEC1850BAC 50 | Slam.Dunk.E45.2013.720p.HDTV.x264.AAC-NGB.mkv|285266576|32BC00B6CF363198AD0DC552BC36FA461E30CFF7|F8B35C8B680A2A2D5D3A5F74A362D06BFAF65B60 51 | Slam.Dunk.E89.2013.720p.HDTV.x264.AAC-NGB.mkv|264241733|38B5CA0FCC464F3B563F2885BB633E5DFCD84368|1447A9CACD63F239B85E5CE6BDBD3B9B9E7CD62E 52 | Slam.Dunk.E05.2013.720p.HDTV.x264.AAC-NGB.mkv|241939728|6558171D87B48BCFBD120E7DCD7DDEE1306B6B85|38998FF9D7809A41AF9763E8F92AED86F98370A5 53 | Slam.Dunk.E59.2013.720p.HDTV.x264.AAC-NGB.mkv|290873547|14BA4467361B5540B25C562720D730494937D1E3|BAE9232769392A9CA40B46015B6402FB9807208E 54 | Slam.Dunk.E56.2013.720p.HDTV.x264.AAC-NGB.mkv|286921681|146DC49880F332EBBA3C0DBBB1377D5194D4544D|DBCFBDCFCC01A88C32600DB850796515B3ED6D24 55 | Slam.Dunk.E74.2013.720p.HDTV.x264.AAC-NGB.mkv|283211745|AD681D56F09D983ACD7B548AADA990E78300F352|F056596E71C4EB939B85F36D391CD31F72C05498 56 | Slam.Dunk.E24.2013.720p.HDTV.x264.AAC-NGB.mkv|323126148|9F84B54B1A8C54548CBC2A09FC75AA807D57A17D|208BC3837CA2D4C3EFBC0E414AA44DCE89CF62AC 57 | Slam.Dunk.E30.2013.720p.HDTV.x264.AAC-NGB.mkv|285523294|AD42087A0D9C517790D9BA95D827BB2BA9A696CA|7DB1EDC4A5996EF29396008B880E81B7F1D24569 58 | Slam.Dunk.E21.2013.720p.HDTV.x264.AAC-NGB.mkv|320114935|8BA046226B13E126187B62C55C8546733FAD81F6|D42FC0CAA1398A73108F38BA425C381CB326FF00 59 | Slam.Dunk.E23.2013.720p.HDTV.x264.AAC-NGB.mkv|320458439|8EC3748A12A0E8373E6D56D9E90B9A686D4FF879|6B9026EEE09D064D1E346FEF909AE3000646C62C 60 | Slam.Dunk.E70.2013.720p.HDTV.x264.AAC-NGB.mkv|281851501|1CED7DB7436B445921F83DCE9EFD35E6D6731F61|3DC3AC9E7638368D29477E53E1DFB845F5759E80 61 | Slam.Dunk.E90.2013.720p.HDTV.x264.AAC-NGB.mkv|264271672|C2493A3C323F839E5C958B2B943FF2E2968877E8|C76EBF49234A344EB3F76BC4113625A1E3A1A1E5 62 | Slam.Dunk.E51.2013.720p.HDTV.x264.AAC-NGB.mkv|285778187|68ADBD823981EBF8C53B3B6EC786FCC518FFF525|CDFEA982A74B56CA7C01BFD440CC5DCE990B76D2 63 | Slam.Dunk.E34.2013.720p.HDTV.x264.AAC-NGB.mkv|286567601|713F1FF9FC5A9ADCD410D0CF748A7BF137E0FD76|19DB63C782E36E65CAE6A0FE6EDF1B02BC402CEA 64 | Slam.Dunk.E44.2013.720p.HDTV.x264.AAC-NGB.mkv|285649907|2EB65B22AC574F6C61F586CC22F744E5F0514B5C|9EEF693807826240530A8BF95DB55EA5920B72DF 65 | Slam.Dunk.E55.2013.720p.HDTV.x264.AAC-NGB.mkv|286319490|43E80FF779D6EA1374EBCF7516AAA6B1B8A30EC3|53F7C607E6B8B5F4EE45752B3CE5CD18625ABACB 66 | Slam.Dunk.E14.2013.720p.HDTV.x264.AAC-NGB.mkv|318435068|8419E8F0C31CC9F9447E1AFF3D5EA8A80B39546A|188002334F2BA0EB24B8BC1D5F623EF5612BC45A 67 | Slam.Dunk.E50.2013.720p.HDTV.x264.AAC-NGB.mkv|286005563|33C408CAEA64129F13B1C318969091A33927B28A|38BDC876F58E9EEC0526D8E148D0BD122B0F82CB 68 | Slam.Dunk.E80.2013.720p.HDTV.x264.AAC-NGB.mkv|283354612|7A649118B5798F8BE989283D93DBCCF57D60870D|E8C1FF0BAFF0E07E4412576511FEEF226CA10445 69 | Slam.Dunk.E04.2013.720p.HDTV.x264.AAC-NGB.mkv|231970564|C2D1C8D8A9038945CE24B75B39D334EE4A07D757|F587A5E3A55569BB32BC09CD1BD886A492336726 70 | Slam.Dunk.E36.2013.720p.HDTV.x264.AAC-NGB.mkv|286405239|6A8B7C482FB147E54AB45A9F4A626F7C30C336CF|3B15CBB89D84F7EA9613F71AE373A2C44402E0DD 71 | Slam.Dunk.E39.2013.720p.HDTV.x264.AAC-NGB.mkv|286823066|F37481BA299AD6C3FF1F4F1749C5356958A1D564|E08655BCF6ECF3E0FD61497687C3D771CF4626F0 72 | Slam.Dunk.E15.2013.720p.HDTV.x264.AAC-NGB.mkv|321255816|AFF44CF9BCC89535989A14B74844FF10988F9192|BE6F196ECB6A68F2D325097FBE47BD28C970B105 73 | Slam.Dunk.E53.2013.720p.HDTV.x264.AAC-NGB.mkv|285555231|0999035EA0A9A2DC582329F3F869A9232700C396|9ABD03722406DB8CA0B6EB967027AC21BDEEF6DE 74 | Slam.Dunk.E31.2013.720p.HDTV.x264.AAC-NGB.mkv|286007179|CC12D4BC5AD1D17812DC4FED34248CD60C232707|FBDF5AF0647ED27F78E885172A48844D96E70381 75 | Slam.Dunk.E93.2013.720p.HDTV.x264.AAC-NGB.mkv|264351161|DFBE1164EBDE6DE9E7229ABFA7C9A09BC7623E71|9259002C68CA830E73312589EAD48DCF53EBB589 76 | Slam.Dunk.E32.2013.720p.HDTV.x264.AAC-NGB.mkv|285600916|4CDB50788DEAB22322D35A0648DB898A3402AAA9|9AFD9B1BB5DCF30239038BAC1778CCAD790B35DC 77 | Slam.Dunk.E84.2013.720p.HDTV.x264.AAC-NGB.mkv|282991624|69D376A02109D1F93894D1631CD987149C1A0AE6|654C3778508C821462A491EE4A09883715D34200 78 | Slam.Dunk.E09.2013.720p.HDTV.x264.AAC-NGB.mkv|321492152|4182D9C1AFE19140165442B87D9FB3489FA42A40|46BAF85ED0038A01081690CF4C78F47240E52547 79 | Slam.Dunk.E88.2013.720p.HDTV.x264.AAC-NGB.mkv|264195961|E0CD0CABDA26D440161C9B2EFAB0D50F52E9E44E|D5252D0977F7D53E981C73567416A50F85E1BCFA 80 | Slam.Dunk.E91.2013.720p.HDTV.x264.AAC-NGB.mkv|264244103|E6113EF0B92B261747450E70CB433B72357A2B44|C0B2393575E2195577F8C3265151F32C39463351 81 | Slam.Dunk.E69.2013.720p.HDTV.x264.AAC-NGB.mkv|281519683|079EE5A5B4D64FFF0E5AFFDF7700488B74E1E5CF|17CE62EC6D5B86C950FB2624ED908BE870AC6F4A 82 | Slam.Dunk.E18.2013.720p.HDTV.x264.AAC-NGB.mkv|322362376|C8AB4E0160EF736A1EFA05EDE036B8EC90769C94|194FCDC22A3056C77996ECEE47CB9217B7377D27 83 | Slam.Dunk.E64.2013.720p.HDTV.x264.AAC-NGB.mkv|286659889|25EE7D5A079FCD5FA4A0F8C2289DA27CFE488EEF|2A93A574316AC940CBEC72B21F4871DEFDAFE61D 84 | Slam.Dunk.E25.2013.720p.HDTV.x264.AAC-NGB.mkv|320291945|62515DFF7295907CEAD27E6528FA914F77036D5C|8C4A1337CE69D889F2459374D17B06CF858F25C4 85 | Slam.Dunk.E58.2013.720p.HDTV.x264.AAC-NGB.mkv|291612956|76327CB7E11BEACD9AC26253E5C8A87236B81D75|ADC2BBDFEB9BCFF1BFFAD9B72ADE53CC9946D950 86 | Slam.Dunk.E33.2013.720p.HDTV.x264.AAC-NGB.mkv|285900501|A564D4DF13BD7317FD0DAED0214CC0D2E3B06358|39B2014FD769A94407269551B76C8CC6BE1B200B 87 | Slam.Dunk.E12.2013.720p.HDTV.x264.AAC-NGB.mkv|321451046|3CE6658F8ED00807843A3AA87FFF88F39F664368|D059A0664A92281577DDCC6C9E763D02471C1256 88 | Slam.Dunk.E26.2013.720p.HDTV.x264.AAC-NGB.mkv|284014693|B5D73AB5A340635224C85961FB5976884EECE3A2|2A8E7CD7E48318FA154083FCB41C406E54A8EF15 89 | Slam.Dunk.E41.2013.720p.HDTV.x264.AAC-NGB.mkv|286698480|3F171A9237E4480A7873DB13602CC7177E4D94F1|24B937882DD0341A4B43A301858FCED397C33585 90 | Slam.Dunk.E65.2013.720p.HDTV.x264.AAC-NGB.mkv|283607169|3F8F40ACDFD37EFC90484D5D038671B16FC46151|BB7701BEE899CD764791BAE8F81AAF16F81063A4 91 | Slam.Dunk.E43.2013.720p.HDTV.x264.AAC-NGB.mkv|285804137|4589F3EC252D6D001D1E5B20DF1B13B772F23545|D1C7190B3A92185F20F47D4258D78B68A1F4CCC1 92 | Slam.Dunk.E67.2013.720p.HDTV.x264.AAC-NGB.mkv|282580895|036EAB41E58D03DD5FA8783E6518D0F9291419E9|7430E518DACC674B36C47B12A270F5C95D205B86 93 | Slam.Dunk.E95.2013.720p.HDTV.x264.AAC-NGB.mkv|264294176|60B4123EEC426B1215F33AD3077A7D377E64057F|02EB195F50E911C40FB940314239A653E8DE5A13 94 | Slam.Dunk.E72.2013.720p.HDTV.x264.AAC-NGB.mkv|283333889|7F00D1D8C04A03743D17C7E9EBBABE3241C0B2AB|F4C472D7032FA888E452E1484D583383CFA70F77 95 | Slam.Dunk.E66.2013.720p.HDTV.x264.AAC-NGB.mkv|283397625|8A95236B47E106E532FDEDF948DBB670B60395E9|B8B78DCFA565B61868883EEE465690C0A46CE3AC 96 | Slam.Dunk.E101.2013.720p.HDTV.x264.AAC-NGB.mkv|258483115|5D78E33185A2EC0B740E5F483BB52A869A16C52F|524BCFB2DFAF16C209B3DDA898A2A9F9AF44F7F2 97 | Slam.Dunk.E71.2013.720p.HDTV.x264.AAC-NGB.mkv|282033318|247943923CB575AA96F16A5A27B28841BC976DCC|F309C0B19FF15BFF57E3F9B447DF0C19B0630640 98 | Slam.Dunk.E07.2013.720p.HDTV.x264.AAC-NGB.mkv|242829958|4B5BE3E5F9A621F80D2BEB6CFE577FDEEC6D2C63|201067E58C60FEBEAF336A40BDA0EACD3DF17DDB 99 | Slam.Dunk.E01.2013.720p.HDTV.x264.AAC-NGB.mkv|282429725|A09D1FE73E30BA6066B821A85D206B3CB10725F2|D42747CA1DBC11F92657E7A821EBB5475369F218 100 | Slam.Dunk.E37.2013.720p.HDTV.x264.AAC-NGB.mkv|285937354|770E0152F01B3C85638D4AF7896178D662B80B4E|18FF4826066EE6D0707CCF63619C1F14BD12FE1E 101 | Slam.Dunk.E38.2013.720p.HDTV.x264.AAC-NGB.mkv|285188554|FEB846A70470CD5A95388EE63CF00FC42ED9EB58|874242E4F2A49066783BE1599D4F23E058C5F98 102 | -------------------------------------------------------------------------------- /fake115upload.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | #coding: utf-8 3 | __author__ = 'T3rry' 4 | 5 | from requests_toolbelt.multipart.encoder import MultipartEncoder 6 | from Crypto.Util.number import bytes_to_long,long_to_bytes 7 | from Crypto.Cipher import PKCS1_v1_5,AES 8 | from Crypto.PublicKey import RSA 9 | from Crypto import Random 10 | from ecdsa import ECDH, NIST224p, SigningKey 11 | from binascii import a2b_hex, b2a_hex 12 | import hashlib,base64,lz4.block,zlib 13 | import sys,os,time,platform 14 | import json,requests,random 15 | import getopt,ctypes,codecs 16 | import urllib 17 | 18 | 19 | COOKIE = 'need your cookie' 20 | 21 | class Fake115Client(object): 22 | 23 | def __init__(self, cookie): 24 | self.app_version='25.2.2' 25 | self.api_version = '2.0.1.7' 26 | self.cookie=cookie 27 | self.ua='Mozilla/5.0; Mac OS X/10.15.7; 115Desktop/2.0.1.7' 28 | self.content_type='application/x-www-form-urlencoded' 29 | self.header={"User-Agent" : self.ua,"Content-Type": self.content_type, "Cookie":self.cookie } 30 | self.crc_salt= '^j>WD3Kr?J2gLFjD4W2y@' 31 | self.md5_salt = 'Qclm8MGWUv59TnrR0XPg' 32 | self.remote_pubkey ='0457A29257CD2320E5D6D143322FA4BB8A3CF9D3CC623EF5EDAC62B7678A89C91A83BA800D6129F522D034C895DD2465243ADDC250953BEEBA' 33 | self.private_key = RSA.construct((0x8C81424BC166F4918756E9F7B22EFAA03479B081E61896872CB7C51C910D7EC1A4CE2871424D5C9149BD5E08A25959A19AD3C981E6512EFDAB2BB8DA3F1E315C294BD117A9FB9D8CE8E633B4962E087C629DC6CA3A149214B4091EF2B0363CB3AE6C7EE702377F055ED3CD93F6C342256A76554BBEA7F203437BBE65F2DA2741, 0x10001, 0x3704DAB00D80C25E464FFB785A16D95F688D0A5823811758C16308D5A1DB55FA800D967A9B4AEDE79AA783ADFFDCDB23541C80B8D436901F172B1CCCA190B224DBE777BF18B96DD9A30AACE8780350793A4F90A645A7747EF695622EADBE23A4C6D88F22E87842B43B35486C2D1B5B1FA77DB3528B0910CA84EDB7A46AFDBED1)) 34 | self.public_key = RSA.construct((0x8686980c0f5a24c4b9d43020cd2c22703ff3f450756529058b1cf88f09b8602136477198a6e2683149659bd122c33592fdb5ad47944ad1ea4d36c6b172aad6338c3bb6ac6227502d010993ac967d1aef00f0c8e038de2e4d3bc2ec368af2e9f10a6f1eda4f7262f136420c07c331b871bf139f74f3010e3c4fe57df3afb71683, 0x10001)) 35 | self.g_key_l = a2b_hex('7806AD4C33865D184C013F46') 36 | self.g_key_s = a2b_hex('2923215E') 37 | self.g_kts = a2b_hex('F0E569AEBFDCBF8A1A45E8BE7DA673B8DE8FE7C445DA86C49B648B146AB4F1AA3801359E26692C86006B4FA5363462A62A966818F24AFDBD6B978F4D8F8913B76C8E93ED0E0D483ED72F88D8FEFE7E8650954FD1EB832634DB667B9C7E9D7A8132EAB633DE3AA95934663BAABA816048B9D5819CF86C8477FF5478265FBEE81E369F34805C452C9B76D51B8FCCC3B8F5') 38 | self.curve = NIST224p 39 | self.m115_l_rnd_key=None 40 | self.m115_s_rnd_key=None 41 | self.local_private_key=None 42 | self.local_public_key=None 43 | self.aes_key=None 44 | self.aes_iv=None 45 | self.user_id=None 46 | self.user_key=None 47 | self.std_out_handle=None 48 | self.filecount=0 49 | self.cid=0 50 | 51 | sk =SigningKey.generate(curve=self.curve) 52 | ecdh = ECDH(curve=self.curve) 53 | ecdh.load_private_key(sk) 54 | local_public_key = ecdh.get_public_key().to_string() 55 | 56 | self.local_public_key=b'\x29'+local_public_key 57 | ecdh.load_received_public_key_bytes(a2b_hex(self.remote_pubkey)) 58 | secret = ecdh.generate_sharedsecret_bytes() 59 | self.aes_key=secret[0:16] 60 | self.aes_iv=secret[-16:] 61 | 62 | if self.get_userkey() is False: 63 | print('Get userkey info failed!') 64 | 65 | def m115_init(self): 66 | self.g_key_l = a2b_hex('7806AD4C33865D184C013F46') 67 | self.g_key_s = a2b_hex('2923215E') 68 | 69 | def m115_setkey(self,randkey,sk_len): 70 | 71 | length=sk_len *(sk_len-1) 72 | index=0 73 | xorkey=b'' 74 | if randkey: 75 | for i in range(0,sk_len): 76 | x=(randkey[i] + self.g_kts[index])&0xff 77 | xorkey += chr((self.g_kts[length]) ^ x).encode('latin1') 78 | length -=sk_len 79 | index +=sk_len 80 | 81 | if (sk_len == 4): 82 | self.g_key_s=xorkey 83 | elif (sk_len == 12): 84 | self.g_key_l = xorkey 85 | 86 | def xor115_enc(self,src,key): 87 | header='' 88 | pad= len(src)%4 89 | 90 | if pad >0: 91 | for i in range(0,pad): 92 | header+=chr((src[i])^(key[i])) 93 | src=src[pad:] 94 | lkey=len(key) 95 | secret=[] 96 | num=0 97 | for s in src: 98 | if num>=lkey: 99 | num=num%lkey 100 | secret.append( chr( (s)^(key[num]) ) ) 101 | num+=1 102 | 103 | return (header+"".join(secret)) 104 | 105 | def m115_encode(self,plaintext): 106 | self.m115_init() 107 | self.m115_l_rnd_key =Random.new().read(16) 108 | self.m115_setkey(self.m115_l_rnd_key,4) 109 | tmp = self.xor115_enc(plaintext.encode('latin1'), self.g_key_s)[::-1] 110 | xortext = self.xor115_enc(tmp.encode('latin1'), self.g_key_l).encode('latin1') 111 | cipher = PKCS1_v1_5.new(self.public_key) 112 | ciphertext = cipher.encrypt(self.m115_l_rnd_key+xortext) 113 | ciphertext = urllib.parse.quote(base64.b64encode(ciphertext)) 114 | 115 | return ciphertext 116 | 117 | def m115_decode(self,ciphertext): 118 | key_size=16 119 | block_size=128 120 | plaintext=b'' 121 | ciphertext=base64.b64decode(ciphertext) 122 | block=len(ciphertext)//block_size 123 | 124 | for i in range(0,block): 125 | m = long_to_bytes(pow(bytes_to_long(ciphertext[i*128:block_size]), self.public_key.e, self.public_key.n)) 126 | m=m[m.index(b'\x00')+1:] 127 | plaintext += m 128 | block_size += 128 129 | 130 | self.m115_s_rnd_key=plaintext[0:key_size] 131 | plaintext=plaintext[key_size:] 132 | self.m115_setkey(self.m115_l_rnd_key,4) 133 | self.m115_setkey(self.m115_s_rnd_key,12) 134 | tmp= self.xor115_enc(plaintext,self.g_key_l)[::-1] 135 | plaintext= self.xor115_enc(tmp.encode('latin1'),self.g_key_s) 136 | return plaintext 137 | 138 | def ec115_get_token(self,data): #md5(fileid+filesize+preid+uid+timestap+md5(uid)) 139 | m = hashlib.md5() 140 | m.update(data) 141 | return m.hexdigest() 142 | 143 | def ec115_compress_decode(self,data): 144 | size=ord(data[0])+(ord(data[1])<<8) 145 | return(lz4.block.decompress(data[2:size+2],0x2000)) 146 | 147 | def ec115_encode_data(self,data): 148 | mode = AES.MODE_ECB 149 | BS = AES.block_size 150 | pad =lambda s: s +(BS - len(s)% BS)* chr(0) 151 | unpad =lambda s : s[0:-ord(s[-1])] 152 | data=pad(data) 153 | cipher_text='' 154 | xor_key=self.aes_iv 155 | tmp='' 156 | 157 | cryptos = AES.new(self.aes_key, mode) 158 | for i in range(0,len(data)): 159 | tmp+=chr(ord(data[i])^ord(xor_key[i%16])) 160 | if((i%16)==15): 161 | xor_key=cryptos.encrypt(tmp) 162 | cipher_text += xor_key 163 | tmp='' 164 | 165 | return cipher_text 166 | 167 | def ec115_encode_token(self,timestap=None): 168 | r1=random.randint(0x0,0xff) 169 | r2=random.randint(0x0,0xff) 170 | tmp='' 171 | 172 | try: 173 | for i in range(0,15): 174 | tmp+=chr(ord(self.local_public_key[i])^r1) 175 | tmp+=chr(r1)+chr(0x73^r1) 176 | timestap=hex(timestap)[2:].decode('hex') 177 | 178 | for i in range(0,3): 179 | tmp+=chr(r1) 180 | for i in range(0,4): 181 | tmp+=chr(r1^ord(timestap[3-i])) 182 | for i in range(15,30): 183 | tmp+=chr(ord(self.local_public_key[i])^r2) 184 | tmp+=chr(r2)+chr(1^r2) 185 | for x in xrange(0,3): 186 | tmp+=chr(r2) 187 | 188 | crc= zlib.crc32(self.crc_salt+tmp)& 0xffffffff 189 | h_crc32= hex(crc)[2:] 190 | if(len(h_crc32)%2 !=0): 191 | h_crc32='0'+h_crc32 192 | h_crc32=h_crc32.decode('hex') 193 | for i in range(0,4): 194 | tmp+=(h_crc32[3-i]) 195 | 196 | except Exception as e: 197 | print(e) 198 | 199 | return base64.b64encode(tmp) 200 | 201 | def ec115_decode(self,data): 202 | BS = AES.block_size 203 | pad =lambda s: s +(BS - len(s)% BS)* chr(0) 204 | unpad =lambda s : s[0:-ord(s[-1])] 205 | cipher = AES.new(self.aes_key, AES.MODE_CBC,self.aes_iv) 206 | lz4_buff=cipher.decrypt((data[0:-(len(data)%16)])) 207 | 208 | return self.ec115_compress_decode(lz4_buff) 209 | 210 | def get_file_size(self,file): 211 | return str(os.path.getsize(file)) 212 | 213 | def get_userkey(self): 214 | try: 215 | r = requests.get("http://proapi.115.com/app/uploadinfo",headers=self.header) 216 | resp=json.loads(r.content) 217 | self.user_id=str(resp['user_id']) 218 | self.user_key=str(resp['userkey']).upper() 219 | except Exception as e: 220 | print("Explired cookie !",e) 221 | return False 222 | 223 | def show_folder_path(self): 224 | url='https://webapi.115.com/files?aid=1&cid='+self.cid+'&o=user_ptime&asc=0&offset=0&show_dir=1&limit=115&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&type=&star=&is_q=&is_share=' 225 | r = requests.get(url,headers=self.header) 226 | resp=json.loads(r.content)['path'] 227 | path='{' 228 | for f in resp: 229 | path+= f['name']+'=>' 230 | path=path[:-2]+'}' 231 | self.log(path,False,"PATH") 232 | 233 | def get_preid(self,pickcode): 234 | 235 | file_url=self.get_download_url_by_pc(pickcode) 236 | 237 | token=self.cookie 238 | try: 239 | token =r.headers['Set-Cookie'].split(';')[0] 240 | except Exception as e: 241 | pass 242 | 243 | head = { "User-Agent" : self.ua,"Range":"bytes=0-131071","Cookie":token} 244 | r2= requests.get(file_url,headers=head) 245 | sha = hashlib.sha1() 246 | sha.update(r2.content) 247 | preid = sha.hexdigest() 248 | return preid.upper() 249 | 250 | def get_download_url_by_pc(self,pc): 251 | url = 'http://proapi.115.com/pc/ufile/downurl' 252 | pc_data = ('{"pickcode":"%s","app_ver":"%s"}') % ( pc,self.api_version) 253 | data='data='+self.m115_encode(pc_data) 254 | r = requests.post(url, data=data,headers=self.header) 255 | ciphertext=(json.loads(r.content)['data']) 256 | plaintext=self.m115_decode(ciphertext) 257 | jtext=json.loads(plaintext).items() 258 | 259 | for key, value in jtext: 260 | url =value['url']['url'] 261 | 262 | return url 263 | 264 | def get_link(self, filename): 265 | try: 266 | with open(filename,'rb') as f: 267 | sha = hashlib.sha1() 268 | sha.update(f.read(1024*128)) 269 | BlockHASH = sha.hexdigest().upper() 270 | f.seek(0,0) 271 | sha = hashlib.sha1() 272 | sha.update(f.read()) 273 | TotalHASH=sha.hexdigest().upper() 274 | link= filename+'|'+str(os.path.getsize(filename))+'|'+TotalHASH+'|'+BlockHASH+'\n' 275 | return link 276 | except Exception as e: 277 | print(e) 278 | return 279 | 280 | def import_file_with_sha1(self,preid,fileid,filesize,filename): # pc api 281 | fileid=fileid 282 | target='U_1_'+str(self.cid) 283 | tm = int(time.time()) 284 | s1=hashlib.sha1((self.user_id+fileid+target+'0').encode('utf8')).hexdigest() 285 | s2=self.user_key+s1+"000000" 286 | sig = hashlib.sha1(s2.encode('utf8')).hexdigest().upper() 287 | 288 | h1 = hashlib.md5(self.user_id.encode('utf8')).hexdigest() 289 | token = hashlib.md5((self.md5_salt+fileid +filesize+preid+self.user_id+str(tm)+h1+self.api_version).encode('utf8')).hexdigest() 290 | url = ("http://uplb.115.com/3.0/initupload.php?appid=0&appversion=%s&format=json&isp=0&sig=%s&t=%d&topupload=0&rt=0&token=%s") % (self.api_version,sig,tm,token) 291 | postData = ('fileid=%s&filename=%s&filesize=%s&preid=%s&target=%s&userid=%s') % (fileid, filename, filesize, preid, target, self.user_id) 292 | 293 | r = requests.post(url, data=(postData.encode('utf8')),headers=self.header) 294 | response = (r.content) 295 | 296 | try: 297 | if json.loads(response)['status']==2 and json.loads(response)['statuscode']==0: 298 | self.log(filename+' upload completed.',False,"OK") 299 | return True 300 | else: 301 | self.log(filename+' upload failed.',True,"ERROR") 302 | return False 303 | except Exception as e: 304 | print(e) 305 | return 306 | 307 | def import_file_with_sha1_android(preid, fileid, filesize, filename): # mobile api 308 | fileid=fileid.upper() 309 | quickid=fileid 310 | target='U_1_'+str(self.cid) 311 | hash=hashlib.sha1((user_id+fileid+quickid+pickcode+target+'0')).hexdigest() 312 | a=userkey+hash+end_string 313 | sig=hashlib.sha1(a).hexdigest().upper() 314 | url="http://uplb.115.com/3.0/initupload.php?isp=0&appid=0&appversion="+self.app_version+"&format=json&sig="+sig 315 | postData={ 316 | 'preid':preid, 317 | 'filename':filename, 318 | 'quickid':fileid, 319 | 'user_id':user_id, 320 | 'app_ver':self.app_version, 321 | 'filesize':filesize, 322 | 'userid':user_id, 323 | 'exif':'', 324 | 'target':target, 325 | 'fileid':fileid 326 | } 327 | r = requests.post(url, data=postData,headers=header) 328 | try: 329 | if json.loads(r.content)['status']==2 and json.loads(r.content)['statuscode']==0: 330 | printInfo(filename+' upload completed.',False,"OK") 331 | return True 332 | else: 333 | printInfo(filename+' upload failed.',True,"ERROR") 334 | return False 335 | except: 336 | return False 337 | 338 | def upload_file_with_sha1(self,filename): 339 | self.log( "Trying fast upload...",False,"INFO") 340 | with open(filename,'rb') as f: 341 | sha1 = hashlib.sha1() 342 | sha1.update(f.read(1024*128)) 343 | blockhash = sha1.hexdigest().upper() 344 | f.seek(0,0) 345 | sha1 = hashlib.sha1() 346 | while True: 347 | data = f.read(64 * 1024) 348 | if not data: 349 | break 350 | sha1.update(data) 351 | totalhash=sha1.hexdigest().upper() 352 | 353 | ret=self.import_file_with_sha1(blockhash,totalhash,self.get_file_size(filename),os.path.basename(filename)) 354 | return ret 355 | 356 | def export_link_to_file(self,outfile,cid): 357 | uri="http://webapi.115.com/files?aid=1&cid="+str(cid)+"&o=user_ptime&asc=0&offset=0&show_dir=1&limit=5000&code=&scid=&snap=0&natsort=1&source=&format=json" 358 | url='http://aps.115.com/natsort/files.php?aid=1&cid='+str(cid)+'&o=file_name&asc=1&offset=0&show_dir=1&limit=5000&code=&scid=&snap=0&natsort=1&source=&format=json&type=&star=&is_share=&suffix=&custom_order=&fc_mix=' 359 | 360 | resp='' 361 | r = requests.get(uri,headers=self.header) 362 | if ('data' in json.loads(r.content)): 363 | resp=json.loads(r.content)['data'] 364 | 365 | else: 366 | r = requests.get(url,headers=self.header) 367 | resp=json.loads(r.content)['data'] 368 | 369 | of= codecs.open(outfile,'a+', encoding='utf-8') 370 | for d in resp: 371 | if 'fid' in d: 372 | 373 | self.filecount+=1 374 | try: 375 | # print(d['pc']) 376 | preid=self.get_preid(d['pc']) 377 | self.log(d['n']+'|'+str(d['s'])+'|'+d['sha']+'|'+preid,False,str(self.filecount)) 378 | of.write(d['n']+'|'+str(d['s'])+'|'+d['sha']+'|'+preid+'\n') 379 | except Exception as e: 380 | print(e) 381 | of.write(d['n']+'|'+str(d['s'])+'|'+d['sha']+'|'+preid+'\n') 382 | continue 383 | elif 'pid' in d: 384 | cid=d['cid'] 385 | self.export_link_to_file(outfile,cid) 386 | of.close() 387 | 388 | def import_file_from_link(self,file): # 389 | for l in codecs.open(file,'r','utf-8'): 390 | link=l.split('|') 391 | filename=link[0] 392 | filesize=link[1] 393 | fileid=link[2] 394 | preid=link[3].strip() 395 | if(len(fileid)!=40 and len(preid)!=40): 396 | print('Error link!') 397 | return 398 | self.import_file_with_sha1(preid,fileid,filesize,filename) 399 | 400 | def upload_file(self,filename): 401 | if self.upload_file_with_sha1(filename): 402 | return 403 | 404 | self.log("Trying local upload...", False, "INFO") 405 | uri = 'http://uplb.115.com/3.0/sampleinitupload.php' 406 | 407 | postdata={"userid":self.user_id,"filename":os.path.basename(filename),"filesize":self.get_file_size(filename),"target":"U_1_"+str(self.cid)} 408 | r = requests.post(uri,headers=self.header,data=postdata) 409 | resp=json.loads(r.content) 410 | 411 | req_headers = {'Content-Type': "multipart/form-data; boundary=----7d4a6d158c9"} 412 | m = MultipartEncoder(fields=[('name', os.path.basename(filename)), 413 | ('key', resp['object']), 414 | ('policy',resp['policy']), 415 | ('OSSAccessKeyId', resp['accessid']), 416 | ('success_action_status', '200'), 417 | ( 'callback',resp['callback']), 418 | ('signature',resp['signature']), 419 | ('file',(os.path.basename(filename),open(filename, 'rb'), 'video/mp4'))], 420 | boundary='----7d4a6d158c9' 421 | ) 422 | r = requests.post(resp['host'],headers=req_headers,data=m) 423 | try: 424 | if json.loads(r.content)['state']==True and json.loads(r.content)['code']==0: 425 | self.log(os.path.basename(filename)+' upload completed.',False,"OK") 426 | else: 427 | self.log(os.path.basename(filename)+' upload failed.',False,"OK") 428 | except Exception as e: 429 | print('error',e) 430 | 431 | def build_links_from_disk(self,outfile): 432 | self.log(os.getcwd(),False,'PATH') 433 | files = os.listdir(os.getcwd()) 434 | of= codecs.open(outfile,'a+','utf-8') 435 | c=0 436 | for f in files: 437 | c+=1 438 | if os.path.isfile(f): 439 | ret= self.get_link(f) 440 | self.log(ret,False,str(c)) 441 | of.write(ret) 442 | of.close() 443 | 444 | def set_cmd_text_color(self,color): 445 | Bool = ctypes.windll.kernel32.SetConsoleTextAttribute(self.std_out_handle, color) 446 | return Bool 447 | 448 | def resetColor(self): 449 | self.set_cmd_text_color(0x0c | 0x0a | 0x09) 450 | 451 | def log(self,info,erorr,notice=''): 452 | sysstr = platform.system() 453 | if erorr==True: 454 | if(sysstr =="Windows"): 455 | self.std_out_handle = ctypes.windll.kernel32.GetStdHandle(-11) 456 | self.set_cmd_text_color(0x0c) 457 | sys.stdout.write('['+notice+'] '+info+'\n') 458 | self.resetColor() 459 | else: 460 | print('\033[31m'+'['+notice+'] '+info) 461 | else: 462 | if(sysstr =="Windows"): 463 | self.std_out_handle = ctypes.windll.kernel32.GetStdHandle(-11) 464 | self.set_cmd_text_color(0x0a) 465 | sys.stdout.write('['+notice+'] '+info+'\n') 466 | self.resetColor() 467 | else: 468 | print('\033[32m'+'['+notice+'] '+info) 469 | 470 | def usage(): 471 | print( 472 | """ 473 | Usage: 474 | -c cid : Folder cid (default set 0) 475 | -u filename: Upload file form local disk 476 | -i filename: Import file from hashlink list 477 | -o filename: Export hashlink list from 115 478 | -b filename: Build file hashlink from local disk 479 | """ 480 | ) 481 | 482 | 483 | if __name__ == '__main__': 484 | 485 | if len(sys.argv) < 2: 486 | usage() 487 | sys.exit() 488 | 489 | cli=Fake115Client(COOKIE) 490 | 491 | if cli.user_key==None: 492 | sys.exit() 493 | 494 | try: 495 | opts, args = getopt.getopt(sys.argv[1:], "u:i:o:b:c:", ["help", "output="]) 496 | for n,v in opts: 497 | if n in ('-c','--cid'): 498 | cli.cid=v 499 | cli.show_folder_path() 500 | for n,v in opts: 501 | if n in ('-u','--upload'): 502 | cli.upload_file(v) 503 | elif n in ('-i','--infile'): 504 | cli.import_file_from_link(v) 505 | elif n in ('-o','--outfile'): 506 | cli.export_link_to_file(v,cli.cid) 507 | print('Total file count :',cli.filecount) 508 | elif n in ('-b','--build'): 509 | cli.build_links_from_disk(v) 510 | 511 | except getopt.GetoptError: 512 | print("Argv error,please input") 513 | -------------------------------------------------------------------------------- /fake115upload.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @author T3rry 3 | // @name 115Link Helper 4 | // @description 115文件备份导入 5 | // @namespace https://github.com/T3rry7f/Fake115Upload 6 | // @version 1.4.5 7 | // @match https://115.com/* 8 | // @grant GM_xmlhttpRequest 9 | // @grant unsafeWindow 10 | // @grant GM_log 11 | // @connect proapi.115.com 12 | // @connect webapi.115.com 13 | // @connect 115.com 14 | // @require https://cdn.bootcss.com/jsSHA/2.3.1/sha1.js 15 | // @require https://greasyfork.org/scripts/5392-waitforkeyelements/code/WaitForKeyElements.js?version=115012 16 | // @require https://cdn.jsdelivr.net/npm/node-forge@0.10.0/dist/forge.min.js 17 | // @downloadURL none 18 | // ==/UserScript== 19 | (function() { 20 | 'use strict'; 21 | 22 | var pub_key='-----BEGIN PUBLIC KEY-----\ 23 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR3rWmeYnRClwLBB0Rq0dlm8Mr\ 24 | PmWpL5I23SzCFAoNpJX6Dn74dfb6y02YH15eO6XmeBHdc7ekEFJUIi+swganTokR\ 25 | IVRRr/z16/3oh7ya22dcAqg191y+d6YDr4IGg/Q5587UKJMj35yQVXaeFXmLlFPo\ 26 | kFiz4uPxhrB7BGqZbQIDAQAB\ 27 | -----END PUBLIC KEY-----' 28 | var private_key='-----BEGIN RSA PRIVATE KEY-----\ 29 | MIICXAIBAAKBgQCMgUJLwWb0kYdW6feyLvqgNHmwgeYYlocst8UckQ1+waTOKHFC\ 30 | TVyRSb1eCKJZWaGa08mB5lEu/asruNo/HjFcKUvRF6n7nYzo5jO0li4IfGKdxso6\ 31 | FJIUtAke8rA2PLOubH7nAjd/BV7TzZP2w0IlanZVS76n8gNDe75l8tonQQIDAQAB\ 32 | AoGANwTasA2Awl5GT/t4WhbZX2iNClgjgRdYwWMI1aHbVfqADZZ6m0rt55qng63/\ 33 | 3NsjVByAuNQ2kB8XKxzMoZCyJNvnd78YuW3Zowqs6HgDUHk6T5CmRad0fvaVYi6t\ 34 | viOkxtiPIuh4QrQ7NUhsLRtbH6d9s1KLCRDKhO23pGr9vtECQQDpjKYssF+kq9iy\ 35 | A9WvXRjbY9+ca27YfarD9WVzWS2rFg8MsCbvCo9ebXcmju44QhCghQFIVXuebQ7Q\ 36 | pydvqF0lAkEAmgLnib1XonYOxjVJM2jqy5zEGe6vzg8aSwKCYec14iiJKmEYcP4z\ 37 | DSRms43hnQsp8M2ynjnsYCjyiegg+AZ87QJANuwwmAnSNDOFfjeQpPDLy6wtBeft\ 38 | 5VOIORUYiovKRZWmbGFwhn6BQL+VaafrNaezqUweBRi1PYiAF2l3yLZbUQJAf/nN\ 39 | 4Hz/pzYmzLlWnGugP5WCtnHKkJWoKZBqO2RfOBCq+hY4sxvn3BHVbXqGcXLnZPvo\ 40 | YuaK7tTXxZSoYLEzeQJBAL8Mt3AkF1Gci5HOug6jT4s4Z+qDDrUXo9BlTwSWP90v\ 41 | wlHF+mkTJpKd5Wacef0vV+xumqNorvLpIXWKwxNaoHM=\ 42 | -----END RSA PRIVATE KEY-----' 43 | 44 | const priv = forge.pki.privateKeyFromPem(private_key); 45 | const pub = forge.pki.publicKeyFromPem(pub_key); 46 | const g_key_l=[0x42,0xda,0x13,0xba,0x78,0x76,0x8d,0x37,0xe8,0xee,0x04,0x91] 47 | const g_key_s=[0x29,0x23,0x21,0x5e] 48 | const g_kts=[0xf0,0xe5,0x69,0xae,0xbf,0xdc,0xbf,0x5a,0x1a,0x45,0xe8,0xbe,0x7d,0xa6,0x73,0x88,0xde,0x8f,0xe7,0xc4,0x45,0xda,0x86,0x94,0x9b,0x69,0x92,0x0b,0x6a,0xb8,0xf1,0x7a,0x38,0x06,0x3c,0x95,0x26,0x6d,0x2c,0x56,0x00,0x70,0x56,0x9c,0x36,0x38,0x62,0x76,0x2f,0x9b,0x5f,0x0f,0xf2,0xfe,0xfd,0x2d,0x70,0x9c,0x86,0x44,0x8f,0x3d,0x14,0x27,0x71,0x93,0x8a,0xe4,0x0e,0xc1,0x48,0xae,0xdc,0x34,0x7f,0xcf,0xfe,0xb2,0x7f,0xf6,0x55,0x9a,0x46,0xc8,0xeb,0x37,0x77,0xa4,0xe0,0x6b,0x72,0x93,0x7e,0x51,0xcb,0xf1,0x37,0xef,0xad,0x2a,0xde,0xee,0xf9,0xc9,0x39,0x6b,0x32,0xa1,0xba,0x35,0xb1,0xb8,0xbe,0xda,0x78,0x73,0xf8,0x20,0xd5,0x27,0x04,0x5a,0x6f,0xfd,0x5e,0x72,0x39,0xcf,0x3b,0x9c,0x2b,0x57,0x5c,0xf9,0x7c,0x4b,0x7b,0xd2,0x12,0x66,0xcc,0x77,0x09,0xa6] 49 | var m115_l_rnd_key= genRandom(16) 50 | var m115_s_rnd_key=[] 51 | var key_s=[] 52 | var key_l=[] 53 | function intToByte(i) { 54 | var b = i & 0xFF; 55 | var c = 0; 56 | if (b >= 256) { 57 | c = b % 256; 58 | c = -1 * (256 - c); 59 | } else { 60 | c = b; 61 | } 62 | return c 63 | } 64 | function stringToArray(s) { 65 | var map = Array.prototype.map 66 | var array = map.call(s,function(x){ 67 | return x.charCodeAt(0); 68 | }) 69 | return array 70 | } 71 | function arrayTostring(array){ 72 | var result = ""; 73 | for(var i = 0; i < array.length; ++i){ 74 | result+= (String.fromCharCode(array[i])); 75 | } 76 | return result; 77 | } 78 | function m115_init() 79 | { 80 | key_s=[] 81 | key_l=[] 82 | } 83 | function m115_setkey(randkey,sk_len) 84 | { 85 | var length=sk_len *(sk_len-1) 86 | var index=0 87 | var xorkey='' 88 | if (randkey) 89 | { 90 | for (var i = 0; i 0){ 112 | for (var i = 0; i =lkey){ 120 | num=num%lkey 121 | } 122 | secret.push((src[i]^key[num])) 123 | num+=1 124 | } 125 | return secret 126 | 127 | } 128 | function genRandom(len) 129 | { 130 | var keys=[] 131 | var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz23456789'; 132 | var maxPos = chars.length; 133 | for (var i = 0; i < len; i++) { 134 | keys.push(chars.charAt(Math.floor(Math.random() * maxPos)).charCodeAt(0)); 135 | } 136 | return keys; 137 | } 138 | function m115_encode(plaintext) 139 | { 140 | console.log('m115_encode:') 141 | m115_init() 142 | key_l=g_key_l 143 | m115_setkey(m115_l_rnd_key,4) 144 | var tmp=xor115_enc(stringToArray(plaintext),key_s).reverse() 145 | var xortext= xor115_enc(tmp,key_l) 146 | var text=arrayTostring(m115_l_rnd_key)+arrayTostring(xortext) 147 | var ciphertext =pub.encrypt(text) 148 | ciphertext=encodeURIComponent(forge.util.encode64(ciphertext)) 149 | return ciphertext 150 | } 151 | function m115_decode(ciphertext) 152 | { 153 | console.log('m115_decode:') 154 | var bciphertext=forge.util.decode64(ciphertext) 155 | var block=bciphertext.length/(128) 156 | var plaintext ='' 157 | var index=0 158 | for (var i = 1; i <=block; ++i) { 159 | plaintext+=priv.decrypt(bciphertext.slice(index, i*128)) 160 | index+=128 161 | } 162 | m115_s_rnd_key =stringToArray(plaintext.slice(0,16)) 163 | plaintext=plaintext.slice(16); 164 | m115_setkey(m115_l_rnd_key,4) 165 | m115_setkey(m115_s_rnd_key,12) 166 | var tmp=xor115_enc(stringToArray(plaintext),key_l).reverse() 167 | plaintext=xor115_enc(tmp,key_s) 168 | return arrayTostring(plaintext) 169 | } 170 | var str=document.URL; 171 | var hProtocol="115://"; 172 | var StoreFolder="导入"; 173 | window.CID=0; 174 | waitForKeyElements("div.file-opr", AddCreateHashLinkBtn); 175 | waitForKeyElements("div.dialog-bottom", AddDownloadSha1Btn); 176 | var style = document.createElement("style"); 177 | style.type = "text/css"; 178 | var text = document.createTextNode("*{margin:0;padding:0;} .pp_align{font-size: 12px;line-height:30px;font-weight: 500;text-align:center;border:1px solid #D1D4D6} .pub_switch_box{font-size: 0;display: inline-block;} .pub_switch { display: none;} .pub_switch + label {display: inline-block;position: relative;width: 56px;height: 32px;background-color: #fafbfa;border-radius: 50px;-webkit-transition: all 0.1s ease-in;transition: all 0.1s ease-in;} .pub_switch + label:after {content: ' ';position: absolute;top: 0;width: 100%;height: 100%;-webkit-transition: box-shadow 0.1s ease-in;transition: box-shadow 0.1s ease-in;left: 0;border-radius: 100px;box-shadow: inset 0 0 0 0 #eee, 0 0 1px rgba(0,0,0,0.4);} .pub_switch + label:before {content: ' ';position: absolute;top: 0px;left: 1px;z-index: 999999;width: 32px;height:32px;-webkit-transition: all 0.1s ease-in;transition: all 0.1s ease-in;border-radius: 100px;box-shadow: 0 3px 1px rgba(0,0,0,0.05), 0 0px 1px rgba(0,0,0,0.3);background: white;} .pub_switch:active + label:after {box-shadow: inset 0 0 0 20px #eee, 0 0 1px #eee;} .pub_switch:active + label:before {width: 37px;} .pub_switch:checked:active + label:before {width: 37px;left: 20px;} .pub_switch + label:active {box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px 1px 3px rgba(0,0,0,0.1);} .pub_switch:checked + label:before {content: ' ';position: absolute;left: 31px;border-radius: 100px;} .pub_switch:checked + label:after {content: ' ';font-size: 1.5em;position: absolute;background: #2777F8;box-shadow: 0 0 1px #2777F8;}"); 179 | style.appendChild(text); 180 | var head = document.getElementsByTagName("head")[0]; 181 | head.appendChild(style); 182 | window.linkText="" 183 | window.reqcount=0 184 | window.cookie=document.cookie 185 | function delay(ms) { 186 | if(ms==0) 187 | { 188 | ms=1000*(Math.floor(Math.random()*(11-4))+4); 189 | console.log(ms); 190 | } 191 | return new Promise(resolve => setTimeout(resolve, ms)) 192 | } 193 | function download(filename,content,contentType) { 194 | if (!contentType) contentType = 'application/octet-stream'; 195 | var a = document.createElement('a'); 196 | var blob = new Blob([content], { 'type': contentType }); 197 | a.href = window.URL.createObjectURL(blob); 198 | a.download = filename; 199 | a.click(); 200 | } 201 | function SetListView() 202 | { 203 | GM_xmlhttpRequest({ 204 | method: "POST", 205 | url: 'https://115.com/?ct=user_setting&ac=set', 206 | headers: { 207 | 'Content-Type': 'application/x-www-form-urlencoded' 208 | }, 209 | data: PostData({ 210 | setting:'{"view_file":"list"}' 211 | }), 212 | responseType: 'json', 213 | onload: function(response) { 214 | if (response.status === 200) { 215 | } 216 | } 217 | }); 218 | } 219 | function AddAutoPickUpBox() 220 | { 221 | var i=document.getElementById('js_top_panel_box'); 222 | if (i!=null){ 223 | var id=document.createElement('div'); 224 | id.setAttribute('class','pub_switch_box'); 225 | var ia=document.createElement('span'); 226 | ia.innerText='自动提取:'; 227 | ia.setAttribute('class','pp_align'); 228 | var ip=document.createElement('input'); 229 | ip.setAttribute('type','checkbox'); 230 | ip.setAttribute('id','autopick'); 231 | ip.setAttribute('class','pub_switch'); 232 | var il=document.createElement('label'); 233 | il.setAttribute('for','autopick'); 234 | id.appendChild(ip); 235 | id.appendChild(il); 236 | i.appendChild(ia); 237 | i.appendChild(id); 238 | } 239 | } 240 | function AddStroeFloder() 241 | { 242 | GM_xmlhttpRequest({ 243 | method: "POST", 244 | url: 'https://webapi.115.com/files/add', 245 | headers: { 246 | 'Content-Type': 'application/x-www-form-urlencoded' 247 | } 248 | , 249 | data: PostData({ 250 | pid:'0', 251 | cname:StoreFolder 252 | }), 253 | responseType: 'json', 254 | onload: function(response) { 255 | if (response.status === 200) { 256 | } 257 | } 258 | }); 259 | } 260 | function Init() 261 | { 262 | //AddAutoPickUpBox(); 263 | var cid=0; 264 | var info=''; 265 | GM_xmlhttpRequest({ 266 | method: "GET", 267 | url: 'https://aps.115.com/natsort/files.php?aid=1&cid=0&o=file_name&asc=1&offset=0&show_dir=1&limit=1150&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&fc_mix=0&type=&star=&is_q=&is_share=', 268 | responseType: 'json', 269 | onload: function(response) { 270 | if (response.status === 200) { 271 | info = response.response; 272 | try 273 | { 274 | info.data.forEach(function (line) { 275 | if(line.n==StoreFolder) 276 | { 277 | window.CID=line.cid; 278 | } 279 | } ) 280 | if(window.CID==0) 281 | { 282 | AddStroeFloder(); 283 | } 284 | } 285 | catch(err) 286 | { 287 | // alert(err); 288 | } 289 | } 290 | } 291 | }); 292 | } 293 | Init(); 294 | function PostData(dict) { 295 | var k, tmp, v; 296 | tmp = []; 297 | for (k in dict) { 298 | v = dict[k]; 299 | tmp.push(k + "=" + v); 300 | } 301 | console.log(tmp.join('&')) 302 | return tmp.join('&'); 303 | }; 304 | function UrlData(dict) { 305 | var k, tmp, v; 306 | tmp = []; 307 | for (k in dict) { 308 | v = dict[k]; 309 | tmp.push((encodeURIComponent(k)) + "=" + (encodeURIComponent(v))); 310 | } 311 | return tmp.join('&'); 312 | }; 313 | function GetSig(userid, fileid, target, userkey) { 314 | var sha1, tmp; 315 | sha1 = new jsSHA('SHA-1', 'TEXT'); 316 | sha1.update("" + userid + fileid + fileid+target + "0"); 317 | tmp = sha1.getHash('HEX'); 318 | sha1 = new jsSHA('SHA-1', 'TEXT'); 319 | sha1.update("" + userkey + tmp + "000000"); 320 | return sha1.getHash('HEX', { 321 | outputUpper: true 322 | }); 323 | } 324 | async function test(info,flag) 325 | { 326 | window.linkText="" 327 | if(info[0].indexOf('|')==-1 ){ 328 | GetFilesByCID(info[0]); 329 | await delay(3000); 330 | while(window.reqcount!=0) 331 | { 332 | await delay(50); 333 | } 334 | download(info[1]+"_sha1.txt",window.linkText); 335 | return; 336 | } 337 | GetFileLink(info,flag); 338 | } 339 | function DeleteCookie(resp) 340 | { 341 | try 342 | { 343 | var reg =/set-cookie: .+;/g; 344 | var setcookie=reg.exec(resp)[0].split(';'); 345 | var filecookie=setcookie[0].slice(11)+"; expires=Thu, 01 Jan 1970 00:00:00 UTC;"+setcookie[3]+";domain=.115.com"; 346 | document.cookie =filecookie; 347 | RenewCookie() 348 | return filecookie; 349 | } 350 | catch(err) 351 | { 352 | return null; 353 | } 354 | } 355 | function RenewCookie() 356 | { 357 | var arryCookie=window.cookie.split(';'); 358 | arryCookie.forEach(function (kv) { 359 | document.cookie=kv+";expires=Thu, 01 Jan 2100 00:00:00 UTC;;domain=.115.com" 360 | } 361 | ) 362 | } 363 | function GetFilesByCID(cid) 364 | { 365 | GM_xmlhttpRequest({ 366 | method: "GET", 367 | url: "https://webapi.115.com/files?aid=1&cid="+cid+"&o=user_ptime&asc=0&offset=0&show_dir=1&limit=1150&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&type=&star=&is_share=&suffix=&custom_order=&fc_mix=", 368 | responseType: 'json', 369 | onload: function(response) { 370 | if (response.status === 200) { 371 | var info = response.response; 372 | try 373 | { 374 | info.data.forEach(function (line) { 375 | if(line.cid!=cid) //folder 376 | { 377 | GetFilesByCID(line.cid); 378 | } 379 | else 380 | { 381 | GetFileLink([line.n+'|'+line.s+'|'+line.sha, line.pc,line.fid],false); 382 | } 383 | } 384 | ) 385 | } 386 | catch(err) 387 | { 388 | GM_xmlhttpRequest({ 389 | method: "GET", 390 | url: "https://aps.115.com/natsort/files.php?aid=1&cid="+cid+"&o=file_name&asc=1&offset=0&show_dir=1&limit=1150&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&type=&star=&is_share=&suffix=&custom_order=&fc_mix=0", responseType: 'json', 391 | onload: function(response) { 392 | if (response.status === 200) { 393 | var info = response.response; 394 | try 395 | { 396 | info.data.forEach(function (line) { 397 | if(line.cid!=cid) //folder 398 | { 399 | GetFilesByCID(line.cid); 400 | } 401 | else 402 | { 403 | GetFileLink([line.n+'|'+line.s+'|'+line.sha,line.pc,line.fid],false); 404 | } 405 | } 406 | ) 407 | } 408 | catch(err) 409 | { 410 | alert(err); 411 | } 412 | } 413 | } 414 | }); 415 | } 416 | } 417 | } 418 | }); 419 | } 420 | function CreateHashLink(url,info,cookie,flag){ 421 | 422 | var pre_buff=null; 423 | if(url!==undefined){ 424 | GM_xmlhttpRequest({ 425 | method: "GET", 426 | url: url, 427 | headers: { 428 | "Range": "bytes=0-154112", 429 | "Cookie": cookie 430 | }, 431 | responseType: 'arraybuffer', 432 | onload: function(response,shalink) { 433 | if (response.status === 206) { 434 | window.reqcount-=1 435 | pre_buff = response.response; 436 | try 437 | { 438 | var data= new Uint8Array(pre_buff); 439 | var sha1 = new jsSHA('SHA-1', 'ARRAYBUFFER'); 440 | sha1.update(data.slice(0, 128 * 1024)); 441 | var preid = sha1.getHash('HEX', { 442 | outputUpper: true 443 | }); 444 | console.log(hProtocol+info[0]+'|'+preid); 445 | window.linkText+=hProtocol+info[0]+'|'+preid+'\n' 446 | if(flag){ 447 | var link= prompt("复制链接到剪贴板",hProtocol+info[0]+'|'+preid); 448 | } 449 | } 450 | catch(err) 451 | { 452 | alert(err); 453 | } 454 | } else { 455 | window.reqcount-=1 456 | return GM_log("response.status = " + response.status); 457 | } 458 | } 459 | }); 460 | } 461 | } 462 | function GetFileLink(info,flag) 463 | { 464 | var download_info=null; 465 | GM_xmlhttpRequest({ 466 | method: "POST", 467 | url: 'http://proapi.115.com/app/chrome/downurl', 468 | headers: { 469 | 'Content-Type':'application/x-www-form-urlencoded' 470 | }, 471 | data: PostData({ 472 | data:m115_encode('{"pickcode":"'+info[1]+'"}') 473 | }), 474 | responseType: 'json', 475 | onload: function(response) { 476 | if (response.status === 200) { 477 | download_info = response.response; 478 | console.log(download_info); 479 | var json=m115_decode(download_info.data); 480 | console.log(info) 481 | console.log(json) 482 | var url=JSON.parse(json)[info[2]]['url']['url']; 483 | console.log(url); 484 | window.reqcount+=1 485 | var resp=response.responseHeaders 486 | var setcookie= DeleteCookie(resp) 487 | var filecookie= null; 488 | if(setcookie) 489 | { 490 | filecookie= setcookie; 491 | } 492 | try 493 | { 494 | CreateHashLink(url,info,filecookie,flag); 495 | } 496 | catch(err) 497 | { 498 | alert('请先登录115'+err); 499 | } 500 | } else { 501 | return GM_log("response.status = " + response.status); 502 | } 503 | } 504 | }); 505 | } 506 | function DownLoadFileFromSha1Links(links) 507 | { 508 | if (links=="") 509 | { 510 | alert("链接不能为空"); 511 | return; 512 | } 513 | var uploadinfo=null; 514 | var cid=0; 515 | GM_xmlhttpRequest({ 516 | method: "GET", 517 | url: 'http://proapi.115.com/app/uploadinfo', 518 | responseType: 'json', 519 | onload: function(response) { 520 | if (response.status === 200) { 521 | uploadinfo = response.response; 522 | document.cookie=window.cookie 523 | try 524 | { 525 | var lines=links.split(/\r?\n/); 526 | lines.forEach(function (line) { 527 | if (line.trim()=="") 528 | { 529 | return; 530 | } 531 | var nsf=line.split('|'); 532 | if(nsf[0].substring(0,6)==hProtocol) 533 | { 534 | nsf[0]=nsf[0].substring(6); 535 | } 536 | if(nsf[0]!='' && nsf[1]!='' && nsf[2]!=''&& nsf[3]!=''&&nsf[2].length==40&&nsf[3].length==40) 537 | { 538 | DownFileBySha1JS(uploadinfo.userkey,uploadinfo.user_id,nsf[0],nsf[1],nsf[2],nsf[3]); 539 | } 540 | else 541 | { 542 | alert("链接格式错误!"); 543 | } 544 | }); 545 | } 546 | catch(err) 547 | { 548 | alert('请先登录115'+err); 549 | } 550 | } else { 551 | return GM_log("response.status = " + response.status); 552 | } 553 | } 554 | }); 555 | } 556 | function DownFileBySha1JS(userkey,user_id,filename,filesize,fileid,preid) 557 | { 558 | var target='U_1_'+window.CID.toString(); 559 | GM_xmlhttpRequest({ 560 | method: 'POST', 561 | url: 'http://uplb.115.com/3.0/initupload.php?' + UrlData({ 562 | isp: 0, 563 | appid: 0, 564 | appversion: '25.2.0', 565 | format: 'json', 566 | sig: GetSig(user_id, fileid, target, userkey), 567 | }), 568 | data: PostData({ 569 | preid: preid, 570 | fileid: fileid, 571 | quickid:fileid, 572 | app_ver: '25.2.0', 573 | filename: filename, 574 | filesize: filesize, 575 | exif:'', 576 | target: target, 577 | userid:user_id 578 | }), 579 | responseType: 'json', 580 | headers: { 581 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' 582 | }, 583 | onload: function(response) { 584 | if (response.status === 200) { 585 | if (response.response.status === 2) { 586 | return console.log(''+filename+' 导入成功!'); 587 | } else { 588 | return console.log(''+filename+' 导入失败!'); 589 | } 590 | } else { 591 | return GM_log("response.status = " + response.status); 592 | } 593 | } 594 | }); 595 | } 596 | function GetSha1LinkByliNode(liNode) 597 | { 598 | var type=(liNode.getAttribute("file_type")); 599 | var filename = liNode.getAttribute('title'); 600 | if(type=="0") 601 | { 602 | var fid = liNode.getAttribute('cate_id'); 603 | return [fid,filename]; 604 | } 605 | else 606 | { 607 | var filesize =liNode.getAttribute('file_size'); 608 | var sha1 =liNode.getAttribute('sha1'); 609 | var pickcode=liNode.getAttribute('pick_code'); 610 | var fid = liNode.getAttribute('file_id'); 611 | return [filename+'|'+filesize+'|'+sha1, pickcode,fid]; 612 | } 613 | } 614 | function AddDownloadSha1Btn(jNode) 615 | { 616 | if (document.getElementById('downsha1')==null){ 617 | var id=document.createElement('div'); 618 | id.setAttribute('class','con'); 619 | id.setAttribute('id','downsha1'); 620 | var ia=document.createElement('a'); 621 | ia.setAttribute('class','button'); 622 | ia.setAttribute('href','javascript:;'); 623 | var inode=document.createTextNode("导入"); 624 | ia.appendChild(inode); 625 | id.appendChild(ia); 626 | jNode[0].appendChild(id); 627 | id.addEventListener('click', function (e) { 628 | var links= document.getElementById('js_offline_new_add').value 629 | DownLoadFileFromSha1Links(links); 630 | (document.getElementsByClassName('close')[2].click()); 631 | }) 632 | } 633 | } 634 | function AddCreateHashLinkBtn(jNode) 635 | { 636 | var parentNode=jNode[0].parentNode; 637 | var sha1Link=GetSha1LinkByliNode(parentNode); 638 | var aclass=document.createElement('a'); 639 | 640 | aclass.addEventListener('click', function (e) { 641 | test(sha1Link,true); 642 | }) 643 | var iclass=document.createElement('i'); 644 | var ispan=document.createElement('span'); 645 | var node=document.createTextNode("生成HashLink"); 646 | ispan.appendChild(node); 647 | aclass.appendChild(iclass); 648 | aclass.appendChild(ispan); 649 | jNode[0].appendChild(aclass); 650 | } 651 | })(); 652 | --------------------------------------------------------------------------------