livemeapi.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. const request = require('request-promise-native')
  2. const API = 'https://live.ksmobile.net'
  3. const IAG = 'https://iag.ksmobile.net'
  4. const URL = {
  5. login: `${IAG}/1/cgi/login`,
  6. appLogin: `${API}/sns/appLoginCM`,
  7. accessToken: `${API}/channel/signin`,
  8. channelLogin: `${API}/channel/login`,
  9. userInfo: `${API}/user/getinfo`,
  10. videoInfo: `${API}/live/queryinfo`,
  11. replayVideos: `${API}/live/getreplayvideos`,
  12. keywordSearch: `${API}/search/searchkeyword`,
  13. liveUsers: `${API}/live/newmaininfo`,
  14. fans: `${API}/follow/getfollowerlistship`,
  15. following: `${API}/follow/getfollowinglistship`,
  16. trendingHashtags: `${API}/search/getTags`,
  17. liveBoys: `${API}/live/boys`,
  18. liveGirls: `${API}/live/girls`,
  19. }
  20. class LiveMe {
  21. constructor(params = {}) {
  22. // Login details
  23. this.email = params.email || null
  24. this.password = params.password || null
  25. // Userdata
  26. this.user = null
  27. // Tokens
  28. this.tuid = null
  29. this.token = null
  30. this.accessToken = null
  31. this.sid = null
  32. this.ssoToken = null
  33. this.androidid = createUUID()
  34. this.thirdchannel = 6
  35. if (this.email && this.password) {
  36. this.getAccessTokens()
  37. .then(() => {
  38. console.log('Authenticated with Live.me servers.')
  39. })
  40. .catch(err => {
  41. console.log('Authentication failed.')
  42. })
  43. }
  44. }
  45. setAuthDetails(email, password) {
  46. if ( ! email || ! password) {
  47. return Promise.reject('You need to provide your Live.me email and password.')
  48. }
  49. this.email = email
  50. this.password = password
  51. return this.getAccessTokens()
  52. }
  53. fetch(method, params = {}, qs = {}) {
  54. const url = URL[method] || method
  55. return request(Object.assign({
  56. method: 'POST',
  57. url,
  58. headers: {
  59. d: Math.round(new Date().getTime() / 1000)
  60. },
  61. qs: Object.assign({
  62. vercode: 38551987,
  63. api: 23,
  64. ver: '3.8.55'
  65. }, qs),
  66. json: true,
  67. transform: function (body) {
  68. if (typeof body === 'string') body = JSON.parse(body)
  69. if (body.status === undefined) body.status = 200
  70. if (body.ret === undefined) body.ret = 1
  71. if (body.status != 200 || body.ret != 1) {
  72. throw new Error('Request failed.')
  73. }
  74. return body.data
  75. }
  76. }, params))
  77. }
  78. getAccessTokens() {
  79. if ( ! this.email || ! this.password) {
  80. return Promise.reject('You need to provide your Live.me email and password.')
  81. }
  82. return request({
  83. method: 'POST',
  84. url: URL.login,
  85. headers: {
  86. d: Math.round(new Date().getTime() / 1000),
  87. sig: 'fp1bO-aJwHKoRB0jnsW4hQ6nor8',
  88. sid: '9469C0239535A9E579F8D20E5A4D5C3C',
  89. appid: '135301',
  90. ver: '3.8.55',
  91. 'content-type': 'multipart/form-data; boundary=3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f',
  92. 'user-agent': 'FBAndroidSDK.0.0.1'
  93. },
  94. body: `--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f\r\nContent-Disposition: form-data; name="cmversion"\r\n\r\n38551987\r\n--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f\r\nContent-Disposition: form-data; name="code"\r\n\r\n\r\n--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f\r\nContent-Disposition: form-data; name="name"\r\n\r\n${this.email}\r\n--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f\r\nContent-Disposition: form-data; name="extra"\r\n\r\nuserinfo\r\n--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f\r\nContent-Disposition: form-data; name="password"\r\n\r\n${this.password}\r\n--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f`,
  95. transform: function (body) {
  96. if (typeof body === 'string') body = JSON.parse(body)
  97. if (body.status === undefined) body.status = 200
  98. if (body.ret === undefined) body.ret = 1
  99. if (body.status != 200 || body.ret != 1) {
  100. throw new Error('Request failed.')
  101. }
  102. return body.data
  103. }
  104. })
  105. .then(json => {
  106. this.sid = json.sid
  107. // Set SSO token
  108. this.ssoToken = json.sso_token
  109. // Pass token to login
  110. return json.sso_token
  111. })
  112. .then(ssoToken => {
  113. // Login
  114. return this.fetch('appLogin', {
  115. form: {
  116. 'data[email]': this.email,
  117. 'data[sso_token]': ssoToken,
  118. sso_token: ssoToken
  119. }
  120. })
  121. })
  122. .then(json => {
  123. this.user = json.user
  124. this.tuid = json.user.user_info.uid
  125. this.token = json.token
  126. return json
  127. })
  128. }
  129. getUserInfo(userid) {
  130. if ( ! userid) {
  131. return Promise.reject('Invalid userid.')
  132. }
  133. return this.fetch('userInfo', {
  134. formData: {
  135. userid
  136. }
  137. })
  138. .then(json => {
  139. return json.user
  140. })
  141. }
  142. getVideoInfo(videoid) {
  143. if ( ! videoid) {
  144. return Promise.reject('Invalid videoid.')
  145. }
  146. if ( ! this.user) {
  147. return Promise.reject('Not authenticated with Live.me!')
  148. }
  149. return this.fetch('videoInfo', {
  150. formData: {
  151. videoid,
  152. userid: 0,
  153. tuid: this.tuid,
  154. token: this.token
  155. }
  156. })
  157. .then(json => {
  158. return json.video_info
  159. })
  160. }
  161. getUserReplays(userid, page_index = 1, page_size = 10) {
  162. if ( ! userid) {
  163. return Promise.reject('Invalid userid.')
  164. }
  165. if ( ! this.user) {
  166. return Promise.reject('Not authenticated with Live.me!')
  167. }
  168. return this.fetch('replayVideos', {
  169. formData: {
  170. userid,
  171. page_index,
  172. page_size,
  173. tuid: this.tuid,
  174. token: this.token,
  175. sso_token: this.ssoToken
  176. }
  177. })
  178. .then(json => {
  179. return json.video_info
  180. })
  181. }
  182. getChatHistoryForVideo(url) {
  183. return request(url)
  184. }
  185. getCommentHistoryForReplay(url) {
  186. return request(url)
  187. }
  188. performSearch(query = '', page = 1, pagesize = 10, type, countryCode = '') {
  189. if ([1, 2].indexOf(type) === -1) {
  190. return Promise.reject('Type must be 1 or 2.')
  191. }
  192. return this.fetch('keywordSearch', {
  193. formData: {
  194. keyword: encodeURIComponent(query),
  195. type,
  196. pagesize,
  197. page,
  198. countryCode
  199. }
  200. })
  201. .then(json => {
  202. return json.data_info
  203. })
  204. }
  205. getLive(page_index = 1, page_size = 10, countryCode = '') {
  206. return this.fetch('liveUsers', {
  207. formData: {
  208. page_index,
  209. page_size,
  210. countryCode
  211. }
  212. })
  213. .then(json => {
  214. return json.video_info
  215. })
  216. }
  217. getFans(access_token, page_index = 1, page_size = 10) {
  218. if ( ! access_token) {
  219. return Promise.reject('Invalid access_token (userid).')
  220. }
  221. return this.fetch('fans', {
  222. formData: {
  223. access_token,
  224. page_index,
  225. page_size
  226. }
  227. })
  228. }
  229. getFollowing(access_token, page_index = 1, page_size = 10) {
  230. if ( ! access_token) {
  231. return Promise.reject('Invalid access_token (userid).')
  232. }
  233. return this.fetch('following', {
  234. formData: {
  235. access_token,
  236. page_index,
  237. page_size
  238. }
  239. })
  240. }
  241. getTrendingHashtags() {
  242. return this.fetch('trendingHashtags')
  243. }
  244. getLiveGirls(page_size = 10, page = 1, countryCode = '') {
  245. return this.fetch('liveGirls', {
  246. formData: {
  247. page,
  248. page_size,
  249. countryCode
  250. }
  251. })
  252. }
  253. getLiveBoys(page_size = 10, page = 1, countryCode = '') {
  254. return this.fetch('liveBoys', {
  255. formData: {
  256. page,
  257. page_size,
  258. countryCode
  259. }
  260. })
  261. }
  262. }
  263. module.exports = LiveMe
  264. // Jibberish.
  265. function createUUID(t) {
  266. var e, n, o = [], a = "0123456789abcdef";
  267. for (e = 0; e < 36; e++)
  268. o[e] = a.substr(Math.floor(16 * Math.random()), 1);
  269. return o[14] = "4",
  270. o[19] = a.substr(3 & o[19] | 8, 1),
  271. t ? n = o.join("").substr(0, 32) : (o[8] = o[13] = o[18] = o[23] = "-",
  272. n = o.join("")),
  273. n
  274. }