promUrlShortener.js (3778B)
1 const TUrl = require('tinyurl'); 2 const { promisify } = require('util'); 3 const R = require('request').defaults({ jar: true }); 4 5 const { botAccount, botPass } = require('./config'); 6 7 const request = promisify(R); 8 const get = promisify(R.get); 9 const post = promisify(R.post); 10 11 const url = 'https://meta.wikimedia.org/w/api.php'; 12 const globalState = { 13 mainExecuted: false, 14 }; 15 16 let logintoken; 17 let csrfToken; 18 19 async function getLoginToken() { 20 const res = {}; 21 try { 22 const data = await get({ 23 url, 24 qs: { 25 action: 'query', 26 meta: 'tokens', 27 type: 'login', 28 format: 'json', 29 }, 30 }); 31 const { body } = data; 32 const parsed = JSON.parse(body); 33 res.logintoken = parsed.query.tokens.logintoken; 34 } catch (error) { 35 console.log(error); 36 res.error = error; 37 globalState.error = true; 38 globalState.fallback = true; 39 } 40 return res; 41 } 42 43 async function loginRequest(TOKEN) { 44 const res = {}; 45 try { 46 const data = await post({ 47 url, 48 form: { 49 action: 'login', 50 lgname: botAccount, 51 lgpassword: botPass, 52 lgtoken: TOKEN, 53 format: 'json', 54 }, 55 }); 56 const { body } = data; 57 const parsed = JSON.parse(body); 58 const result = parsed.login.result; 59 if (result != 'Success') { 60 globalState.error = parsed.login.reason; 61 res.error = parsed.login.reason; 62 } else res.result = result; 63 } catch (error) { 64 console.log(error); 65 globalState.error = error; 66 res.error = error; 67 } 68 return res; 69 } 70 71 async function getCsrfToken() { 72 const res = {}; 73 try { 74 const data = await get({ 75 url, 76 qs: { 77 action: 'query', 78 meta: 'tokens', 79 format: 'json', 80 }, 81 }); 82 const { body } = data; 83 const parsed = JSON.parse(body); 84 res.csrfToken = parsed.query.tokens.csrftoken; 85 } catch (error) { 86 res.error = error; 87 globalState.useFallback = true; 88 } 89 return res; 90 } 91 92 async function main() { 93 try { 94 const maybeLoginToken = await getLoginToken(); 95 if (maybeLoginToken.error) globalState.useFallback = true; 96 else { 97 logintoken = maybeLoginToken.logintoken; 98 const maybeSuccess = await loginRequest(logintoken); 99 if (maybeSuccess.error) globalState.useFallback = true; 100 else { 101 const maybeCsrfToken = await getCsrfToken(); 102 if (maybeCsrfToken.error) globalState.useFallback = true; 103 else csrfToken = maybeCsrfToken.csrfToken; 104 } 105 } 106 } catch (error) { 107 console.error(error); 108 globalState.useFallback = true; 109 } 110 globalState.mainExecuted = true; 111 } 112 113 main(); 114 115 async function short(URI) { 116 if (!globalState.mainExecuted) main(); 117 if (!URI) 118 URI = 119 'https://en.wikinews.org/wiki/Astronomer_tells_Wikinews_about_discovery_of_closest_black_hole_known_so_far'; 120 const res = {}; 121 if (!globalState.error && !globalState.useFallback) { 122 try { 123 const data = await post({ 124 url, 125 form: { 126 action: 'shortenurl', 127 url: URI, 128 format: 'json', 129 }, 130 }); 131 const { body } = data; 132 const parsed = JSON.parse(body); 133 if (parsed.error) throw new Error('Rate limit'); 134 res.url = parsed.shortenurl.shorturl; 135 } catch (error) { 136 globalState.useFallback = true; 137 globalState.error = error; 138 res.error = error; 139 res.url = await TUrl.shorten(URI); 140 } 141 } else { 142 try { 143 res.url = await TUrl.shorten(URI); 144 } catch (error) { 145 res.error = error; 146 console.error(error); 147 } 148 } 149 return res; 150 } 151 152 function fallback() { 153 globalState.useFallback = true; 154 } 155 156 function reset() { 157 globalState.mainExecuted = false; 158 globalState.error = false; 159 globalState.useFallback = false; 160 } 161 162 module.exports = { fallback, reset, short };