ids.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import { request, RequestConfig } from './request'
  2. import { createHmac, randomBytes } from 'crypto'
  3. export interface IdsConfig {
  4. endpoint: string
  5. accessKeyId: string
  6. accessKeySecret: string
  7. }
  8. export enum IdsChannel {
  9. Csdn = 1,
  10. Wechat = 2,
  11. Zhihu = 3,
  12. Juejin = 4
  13. }
  14. export type IdsCrawlRule = 'fulldata' | 'extdata'
  15. export interface IdsArticle {
  16. code: IdsChannel
  17. author_id: string | number
  18. cover_url?: string
  19. title: string
  20. author_name?: string
  21. sn_code: string
  22. original_url?: string
  23. source_address: string
  24. is_headline?: 0 | 1
  25. is_original: 0 | 1
  26. body: string
  27. label?: string
  28. published_at: Date
  29. external_read_num?: number
  30. external_see_num?: number
  31. external_like_num?: number
  32. external_comment_num?: number
  33. }
  34. export enum IdsSource {
  35. Manual = 0,
  36. User = 1,
  37. AliyunMarket = 2,
  38. TencentCloudMarket = 3,
  39. HuaweiCloudMarket = 4,
  40. Xiniu = 6,
  41. Website = 7,
  42. }
  43. export interface IdsProvider {
  44. name: string
  45. short_name?: string
  46. tel?: string
  47. email?: string
  48. logo?: string
  49. description?: string
  50. service_time?: string
  51. source: IdsSource
  52. source_pid: string | number
  53. source_url?: string
  54. }
  55. export interface IdsSolutionExtra {
  56. api_gateway: {
  57. service_id: string
  58. api_id: string
  59. dep_api_id?: string[]
  60. }
  61. icon_padding?: number
  62. }
  63. export interface IdsSolution {
  64. uid: number
  65. title: string
  66. description: string
  67. images: string
  68. details: string
  69. plain_text?: string
  70. service_type?: string[]
  71. dimension: 1 | 2
  72. status: number
  73. source: IdsSource
  74. source_id: string
  75. source_pid: string
  76. source_dt?: string
  77. source_url: string
  78. source_tags?: string[]
  79. source_labels?: string
  80. ext_sold?: number
  81. ext_score?: number
  82. skus?: any[]
  83. api?: any[]
  84. doc_path?: string
  85. is_signed?: 1 | 0
  86. type?: 'gateway'
  87. min_price?: number
  88. max_price?: number
  89. extra?: IdsSolutionExtra | string
  90. }
  91. export interface IdsUser {
  92. uid?: string
  93. password: string
  94. mobile?: string
  95. email?: string
  96. nickname: string
  97. introduction?: string
  98. icon_url?: string
  99. source: string
  100. }
  101. const genNonceString = () => randomBytes(8).toString('hex')
  102. export const randomtail = () => `_=${genNonceString()}`
  103. export class Ids {
  104. config: IdsConfig
  105. constructor(config: IdsConfig) {
  106. this.config = config
  107. }
  108. private async request(config: RequestConfig) {
  109. const { endpoint, accessKeyId, accessKeySecret } = this.config
  110. config.baseURL = endpoint
  111. config.url = config.url || '/'
  112. config.params = config.params || {}
  113. config.params.nonce = genNonceString()
  114. const timestamp = Math.floor(Date.now() / 1000)
  115. const data = config.url.toLowerCase() + timestamp
  116. const signature = createHmac('sha256', accessKeySecret).update(data).digest('base64')
  117. config.headers = config.headers || {}
  118. config.headers['Authorization'] = `IDS-HMAC-SHA256 Credential=${accessKeyId}/${timestamp},Signature=${signature}`
  119. const res = await request(config)
  120. if (res.data.status != 1) {
  121. console.error(res.data)
  122. throw new Error(`[${res.data.status}] ${res.data.info}`)
  123. }
  124. return res.data
  125. }
  126. getCrawlAuthors(channel: IdsChannel) {
  127. return this.request({
  128. method: 'POST',
  129. url: '/api/ids/getCrawlAuthors',
  130. data: {
  131. code: channel
  132. }
  133. })
  134. }
  135. getCrawlArticleRules(params: { ids: string[]; channel: IdsChannel }) {
  136. const { ids, channel } = params
  137. return this.request({
  138. method: 'POST',
  139. url: '/api/ids/getCrawlArticleRules',
  140. data: {
  141. code: channel,
  142. sn_codes: ids
  143. }
  144. })
  145. }
  146. putArticle(data: IdsArticle, rule: IdsCrawlRule) {
  147. data.external_read_num = data.external_read_num || 0
  148. data.external_see_num = data.external_see_num || 0
  149. data.external_like_num = data.external_like_num || 0
  150. data.external_comment_num = data.external_comment_num || 0
  151. return this.request({
  152. method: 'POST',
  153. url: `/api/ids/putArticleData`,
  154. params: {
  155. crawl: rule
  156. },
  157. data
  158. })
  159. }
  160. putProvider(data: IdsProvider) {
  161. return this.request({
  162. method: 'POST',
  163. url: `/api/ids/putSourceData`,
  164. data
  165. })
  166. }
  167. putSolution(data: IdsSolution) {
  168. data.ext_sold = data.ext_sold || 0
  169. data.ext_score = data.ext_score || 0
  170. if (data.extra && typeof data.extra === 'object') {
  171. data.extra = JSON.stringify(data.extra)
  172. }
  173. return this.request({
  174. method: 'POST',
  175. url: `/api/ids/putSolutionData`,
  176. data
  177. })
  178. }
  179. createUser(data: IdsUser) {
  180. return this.request({
  181. method: 'POST',
  182. url: `/api/ids/createUser`,
  183. data
  184. })
  185. }
  186. }