Adrià Vilanova MartÃnez | 7e8796c | 2022-01-23 21:46:46 +0100 | [diff] [blame^] | 1 | import {MDCTooltip} from '@material/tooltip'; |
| 2 | import {waitFor} from 'poll-until-promise'; |
| 3 | |
| 4 | import {isOptionEnabled} from '../../common/optionsUtils.js'; |
| 5 | |
| 6 | import {createExtBadge} from './utils/common.js'; |
| 7 | |
| 8 | const kViewUnifiedUserResponseEvent = 'TWPT_ViewUnifiedUserResponse'; |
| 9 | |
| 10 | const kAbuseCategories = [ |
| 11 | ['1', 'Account'], |
| 12 | ['2', 'Display name'], |
| 13 | ['3', 'Avatar'], |
| 14 | ]; |
| 15 | const kAbuseViolationCategories = { |
| 16 | 0: 'NO_VIOLATION', |
| 17 | 1: 'COMMUNITY_POLICY_VIOLATION', |
| 18 | 2: 'LEGAL_VIOLATION', |
| 19 | 3: 'CSAI_VIOLATION', |
| 20 | 4: 'OTHER_VIOLATION', |
| 21 | }; |
| 22 | const kAbuseViolationTypes = { |
| 23 | 0: 'UNSPECIFIED', |
| 24 | 23: 'ACCOUNT_DISABLED', |
| 25 | 55: 'ACCOUNT_HAS_SERVICES_DISABLED', |
| 26 | 35: 'ACCOUNT_HIJACKED', |
| 27 | 96: 'ACCOUNT_LEAKED_CREDENTIALS', |
| 28 | 92: 'ACCOUNT_NOT_SUPPORTED', |
| 29 | 81: 'ARTISTIC_NUDITY', |
| 30 | 66: 'BAD_BEHAVIOR_PATTERN', |
| 31 | 78: 'BAD_ENGAGEMENT_BEHAVIOR_PATTERN', |
| 32 | 79: 'BORDERLINE_HARASSMENT', |
| 33 | 80: 'BORDERLINE_HATE_SPEECH', |
| 34 | 38: 'BOTNET', |
| 35 | 32: 'BRANDING_VIOLATION', |
| 36 | 100: 'CAPITALIZING_TRAGIC_EVENTS', |
| 37 | 105: 'CLOAKING', |
| 38 | 49: 'COIN_MINING', |
| 39 | 7: 'COMMERCIAL_CONTENT', |
| 40 | 97: 'COPPA_REGULATED', |
| 41 | 57: 'COPYRIGHT_CIRCUMVENTION', |
| 42 | 8: 'COPYRIGHTED_CONTENT', |
| 43 | 58: 'COURT_ORDER', |
| 44 | 51: 'CSAI', |
| 45 | 94: 'CSAI_INSPECT', |
| 46 | 52: 'CSAI_CARTOON_HUMOR', |
| 47 | 53: 'CSAI_SOLICITATION', |
| 48 | 108: 'CSAI_NON_APPARENT', |
| 49 | 67: 'DANGEROUS', |
| 50 | 37: 'DATA_SCRAPING', |
| 51 | 86: 'DECEPTIVE_OAUTH_IMPLEMENTATION', |
| 52 | 46: 'DEFAMATORY_CONTENT', |
| 53 | 36: 'DELINQUENT_BILLING', |
| 54 | 30: 'DISRUPTION_ATTEMPT', |
| 55 | 112: 'DOMESTIC_INTERFERENCE', |
| 56 | 22: 'DOS', |
| 57 | 9: 'DUPLICATE_CONTENT', |
| 58 | 68: 'DUPLICATE_LOCAL_PAGE', |
| 59 | 121: 'NON_QUALIFYING_ORGANIZATION', |
| 60 | 115: 'EGREGIOUS_INTERACTION_WITH_MINOR', |
| 61 | 83: 'ENGAGEMENT_COLLUSION', |
| 62 | 41: 'EXPLOIT_ATTACKS', |
| 63 | 65: 'FAKE_USER', |
| 64 | 2: 'FRAUD', |
| 65 | 21: 'FREE_TRIAL_VIOLATION', |
| 66 | 43: 'GIBBERISH', |
| 67 | 101: 'FOREIGN_INTERFERENCE', |
| 68 | 59: 'GOVERNMENT_ORDER', |
| 69 | 10: 'GRAPHICAL_VIOLENCE', |
| 70 | 11: 'HARASSMENT', |
| 71 | 12: 'HATE_SPEECH', |
| 72 | 90: 'IDENTICAL_PRODUCT_NAME', |
| 73 | 60: 'ILLEGAL_DRUGS', |
| 74 | 13: 'IMPERSONATION', |
| 75 | 69: 'IMPERSONATION_WITH_PII', |
| 76 | 116: 'INAPPROPRIATE_INTERACTION_WITH_MINOR', |
| 77 | 45: 'INAPPROPRIATE_CONTENT_SPEECH', |
| 78 | 106: 'INTENTIONAL_THWARTING', |
| 79 | 27: 'INTRUSION_ATTEMPT', |
| 80 | 87: 'INVALID_API_USAGE', |
| 81 | 14: 'INVALID_CONTENT', |
| 82 | 20: 'INVALID_GCE_USAGE', |
| 83 | 120: 'INVALID_STORAGE_USAGE', |
| 84 | 15: 'INVALID_IMAGE_QUALITY', |
| 85 | 88: 'INVALID_API_PRIVACY_POLICY_DISCLOSURE', |
| 86 | 54: 'INVALID_USAGE_OF_IP_PROXYING', |
| 87 | 99: 'KEYWORD_STUFFING', |
| 88 | 61: 'LEGAL_COUNTERFEIT', |
| 89 | 62: 'LEGAL_EXPORT', |
| 90 | 63: 'LEGAL_PRIVACY', |
| 91 | 33: 'LEGAL_REVIEW', |
| 92 | 91: 'LEGAL_PROTECTED', |
| 93 | 70: 'LOW_QUALITY_CONTENT', |
| 94 | 93: 'LOW_REPUTATION_PHONE_NUMBER', |
| 95 | 6: 'MALICIOUS_SOFTWARE', |
| 96 | 40: 'MALWARE', |
| 97 | 113: 'MISLEADING', |
| 98 | 114: 'MISREP_OF_ID', |
| 99 | 89: 'MEMBER_OF_ABUSIVE_GCE_NETWORK', |
| 100 | 84: 'NON_CONSENSUAL_EXPLICIT_IMAGERY', |
| 101 | 1: 'NONE', |
| 102 | 102: 'OFF_TOPIC', |
| 103 | 31: 'OPEN_PROXY', |
| 104 | 28: 'PAYMENT_FRAUD', |
| 105 | 16: 'PEDOPHILIA', |
| 106 | 71: 'PERSONAL_INFORMATION_CONTENT', |
| 107 | 25: 'PHISHING', |
| 108 | 34: 'POLICY_REVIEW', |
| 109 | 17: 'PORNOGRAPHY', |
| 110 | 29: 'QUOTA_CIRCUMVENTION', |
| 111 | 72: 'QUOTA_EXCEEDED', |
| 112 | 73: 'REGULATED', |
| 113 | 24: 'REPEATED_POLICY_VIOLATION', |
| 114 | 104: 'RESOURCE_COMPROMISED', |
| 115 | 107: 'REWARD_PROGRAMS_ABUSE', |
| 116 | 74: 'ROGUE_PHARMA', |
| 117 | 82: 'ESCORT', |
| 118 | 75: 'SPAMMY_LOCAL_VERTICAL', |
| 119 | 39: 'SEND_EMAIL_SPAM', |
| 120 | 117: 'SEXTORTION', |
| 121 | 118: 'SEX_TRAFFICKING', |
| 122 | 44: 'SEXUALLY_EXPLICIT_CONTENT', |
| 123 | 3: 'SHARDING', |
| 124 | 95: 'SOCIAL_ENGINEERING', |
| 125 | 109: 'SUSPICIOUS', |
| 126 | 19: 'TRADEMARK_CONTENT', |
| 127 | 50: 'TRAFFIC_PUMPING', |
| 128 | 76: 'UNSAFE_RACY', |
| 129 | 103: 'UNUSUAL_ACTIVITY_ALERT', |
| 130 | 64: 'UNWANTED_CONTENT', |
| 131 | 26: 'UNWANTED_SOFTWARE', |
| 132 | 77: 'VIOLENT_EXTREMISM', |
| 133 | 119: 'UNAUTH_IMAGES_OF_MINORS', |
| 134 | 85: 'UNAUTHORIZED_SERVICE_RESELLING', |
| 135 | 98: 'CSAI_EXTERNAL', |
| 136 | 5: 'SPAM', |
| 137 | 4: 'UNSAFE', |
| 138 | 47: 'CHILD_PORNOGRAPHY_INCITATION', |
| 139 | 18: 'TERRORISM_SUPPORT', |
| 140 | 56: 'CSAI_WORST_OF_WORST', |
| 141 | }; |
| 142 | |
| 143 | export default class ExtraInfo { |
| 144 | constructor() { |
| 145 | this.lastProfile = { |
| 146 | body: {}, |
| 147 | id: -1, |
| 148 | timestamp: 0, |
| 149 | }; |
| 150 | this.setUpHandlers(); |
| 151 | } |
| 152 | |
| 153 | setUpHandlers() { |
| 154 | window.addEventListener(kViewUnifiedUserResponseEvent, e => { |
| 155 | if (e.detail.id < this.lastProfile.id) return; |
| 156 | |
| 157 | this.lastProfile = { |
| 158 | body: e.detail.body, |
| 159 | id: e.detail.id, |
| 160 | timestamp: Date.now(), |
| 161 | }; |
| 162 | }); |
| 163 | } |
| 164 | |
| 165 | // Add a pretty component which contains |info| to |node|. |
| 166 | addExtraInfoElement(info, node) { |
| 167 | // Don't create |
| 168 | if (info.length == 0) return; |
| 169 | |
| 170 | let container = document.createElement('div'); |
| 171 | container.classList.add('TWPT-extrainfo-container'); |
| 172 | |
| 173 | let badgeCell = document.createElement('div'); |
| 174 | badgeCell.classList.add('TWPT-extrainfo-badge-cell'); |
| 175 | |
| 176 | let badge, badgeTooltip; |
| 177 | [badge, badgeTooltip] = createExtBadge(); |
| 178 | badgeCell.append(badge); |
| 179 | |
| 180 | let infoCell = document.createElement('div'); |
| 181 | infoCell.classList.add('TWPT-extrainfo-info-cell'); |
| 182 | |
| 183 | for (const i of info) { |
| 184 | let iRow = document.createElement('div'); |
| 185 | iRow.append(i); |
| 186 | infoCell.append(iRow); |
| 187 | } |
| 188 | |
| 189 | container.append(badgeCell, infoCell); |
| 190 | node.append(container); |
| 191 | new MDCTooltip(badgeTooltip); |
| 192 | } |
| 193 | |
| 194 | fieldInfo(field, value) { |
| 195 | let span = document.createElement('span'); |
| 196 | span.append(document.createTextNode(field + ': ')); |
| 197 | |
| 198 | let valueEl = document.createElement('span'); |
| 199 | valueEl.style.fontFamily = 'monospace'; |
| 200 | valueEl.textContent = value; |
| 201 | |
| 202 | span.append(valueEl); |
| 203 | return span; |
| 204 | } |
| 205 | |
| 206 | // Profile functionality |
| 207 | injectAtProfile(card) { |
| 208 | waitFor( |
| 209 | () => { |
| 210 | let now = Date.now(); |
| 211 | if (now - this.lastProfile.timestamp < 15 * 1000) |
| 212 | return Promise.resolve(this.lastProfile); |
| 213 | return Promise.reject('Didn\'t receive profile information'); |
| 214 | }, |
| 215 | { |
| 216 | interval: 500, |
| 217 | timeout: 15 * 1000, |
| 218 | }) |
| 219 | .then(profile => { |
| 220 | let info = []; |
| 221 | const abuseViolationCategory = profile.body?.['1']?.['6']; |
| 222 | if (abuseViolationCategory) { |
| 223 | info.push(this.fieldInfo( |
| 224 | 'Abuse category', |
| 225 | kAbuseViolationCategories[abuseViolationCategory] ?? |
| 226 | abuseViolationCategory)); |
| 227 | } |
| 228 | |
| 229 | const profileAbuse = profile.body?.['1']?.['1']?.['8']; |
| 230 | |
| 231 | for (const [index, category] of kAbuseCategories) { |
| 232 | const violation = profileAbuse?.[index]?.['1']?.['1']; |
| 233 | if (violation) { |
| 234 | info.push(this.fieldInfo( |
| 235 | category + ' policy violation', |
| 236 | kAbuseViolationTypes[violation])); |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | const appealCount = profileAbuse?.['4']; |
| 241 | if (appealCount !== undefined) |
| 242 | info.push(this.fieldInfo('Number of appeals', appealCount)); |
| 243 | |
| 244 | this.addExtraInfoElement(info, card); |
| 245 | }) |
| 246 | .catch(err => { |
| 247 | console.error( |
| 248 | 'extraInfo: error while injecting profile extra info: ', err); |
| 249 | }); |
| 250 | } |
| 251 | |
| 252 | injectAtProfileIfEnabled(card) { |
| 253 | isOptionEnabled('extrainfo').then(isEnabled => { |
| 254 | if (isEnabled) return this.injectAtProfile(card); |
| 255 | }); |
| 256 | } |
| 257 | } |