├── README.md ├── main.py └── tokens.txt /README.md: -------------------------------------------------------------------------------- 1 | # Twitch Follow and Unfollow Bot 2 | 3 | 4 | This is a simple twitch bot for sending and removing follows with OAuth tokens 5 | 6 | 7 | This is demonstrating that twitch have no security, educational use only! 8 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import threading 4 | 5 | from itertools import cycle 6 | from colorama import Fore, init 7 | 8 | 9 | init(convert=True) 10 | 11 | 12 | class stats(): 13 | sent = 0 14 | error = 0 15 | 16 | 17 | 18 | def get_username(channel_name): 19 | 20 | json = {"operationName": "ChannelShell", 21 | "variables": { 22 | "login": channel_name 23 | }, 24 | "extensions": { 25 | "persistedQuery": { 26 | "version": 1, 27 | "sha256Hash": "580ab410bcd0c1ad194224957ae2241e5d252b2c5173d8e0cce9d32d5bb14efe" 28 | } 29 | } 30 | } 31 | 32 | headers = { 33 | 'Client-ID': 'kimne78kx3ncx6brgo4mv6wki5h1ko' 34 | } 35 | r = requests.post('https://gql.twitch.tv/gql', json=json, headers=headers) 36 | return r.json()['data']['userOrError']['id'] 37 | 38 | 39 | class Choose_Cookie(): 40 | 41 | def get_token(): 42 | with open('tokens.txt', 'r') as f: 43 | tokens = [line.strip('\n') for line in f] 44 | return tokens 45 | cookie = get_token() 46 | tokens_loop = cycle(cookie) 47 | 48 | 49 | 50 | 51 | sem = threading.Semaphore(200) 52 | 53 | 54 | channel_name = input("Enter channel name > ") 55 | 56 | class Twitch(): 57 | 58 | def follow(): 59 | with sem: 60 | os.system(f'title Success: {stats.sent} ^| Error: {stats.error}') 61 | channel_ID = get_username(channel_name) 62 | 63 | token = next(Choose_Cookie.tokens_loop) 64 | 65 | headers = { 66 | 'Accept': '*/*', 67 | 'Accept-Language': 'en-GB', 68 | 'Authorization': f'OAuth {token}', 69 | 'Client-Id': 'kimne78kx3ncx6brgo4mv6wki5h1ko', 70 | 'Connection': 'keep-alive', 71 | 'Content-Type': 'text/plain;charset=UTF-8', 72 | 'Origin': 'https://www.twitch.tv', 73 | 'Referer': 'https://www.twitch.tv/', 74 | 'Sec-Fetch-Dest': 'empty', 75 | 'Sec-Fetch-Mode': 'cors', 76 | 'Sec-Fetch-Site': 'same-site', 77 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36', 78 | 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"', 79 | 'sec-ch-ua-mobile': '?0', 80 | 'sec-ch-ua-platform': '"Windows"', 81 | } 82 | 83 | data = '[{"operationName":"FollowButton_FollowUser","variables":{"input":{"disableNotifications":false,"targetID":"'+channel_ID+'"}},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"800e7346bdf7e5278a3c1d3f21b2b56e2639928f86815677a7126b093b2fdd08"}}}]' 84 | r = requests.post('https://gql.twitch.tv/gql', headers=headers, data=data) 85 | if r.status_code == 200: 86 | stats.sent += 1 87 | print(f"{Fore.GREEN}[+] Followed {Fore.RESET}{channel_name}{Fore.RESET}\n") 88 | else: 89 | stats.error += 1 90 | print(F"{Fore.RED}Error{Fore.RESET}\n") 91 | 92 | def unfollow(): 93 | with sem: 94 | os.system(f'title Success: {stats.sent} ^| Error: {stats.error}') 95 | channel_ID = get_username(channel_name) 96 | 97 | token = next(Choose_Cookie.tokens_loop) 98 | 99 | headers = { 100 | 'Accept': '*/*', 101 | 'Accept-Language': 'en-GB', 102 | 'Authorization': f'OAuth {token}', 103 | 'Client-Id': 'kimne78kx3ncx6brgo4mv6wki5h1ko', 104 | 'Connection': 'keep-alive', 105 | 'Content-Type': 'text/plain;charset=UTF-8', 106 | 'Origin': 'https://www.twitch.tv', 107 | 'Referer': 'https://www.twitch.tv/', 108 | 'Sec-Fetch-Dest': 'empty', 109 | 'Sec-Fetch-Mode': 'cors', 110 | 'Sec-Fetch-Site': 'same-site', 111 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36', 112 | 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"', 113 | 'sec-ch-ua-mobile': '?0', 114 | 'sec-ch-ua-platform': '"Windows"', 115 | } 116 | 117 | data = '[{"operationName":"FollowButton_UnfollowUser","variables":{"input":{"targetID":"'+channel_ID+'"}},"extensions":{"persistedQuery":{"version":1,"sha256Hash":"f7dae976ebf41c755ae2d758546bfd176b4eeb856656098bb40e0a672ca0d880"}}}]' 118 | r = requests.post('https://gql.twitch.tv/gql', headers=headers, data=data) 119 | if r.status_code == 200: 120 | stats.sent += 1 121 | print(f"{Fore.GREEN}[+] Unfollow {Fore.RESET}{channel_name}{Fore.RESET}\n") 122 | else: 123 | stats.error += 1 124 | print(F"{Fore.RED}Error{Fore.RESET}\n") 125 | 126 | 127 | 128 | def menu(): 129 | print("[1] Follow\n[2] Unfollow") 130 | 131 | choice = int(input(("Enter option > "))) 132 | 133 | if choice == 1: 134 | threads = input("Enter amount of follows > ") 135 | for i in range(int(threads)): 136 | threading.Thread(target=Twitch.follow).start() 137 | 138 | if choice == 2: 139 | threads = input("Enter amount of follows > ") 140 | for i in range(int(threads)): 141 | threading.Thread(target=Twitch.unfollow).start() 142 | 143 | 144 | 145 | 146 | 147 | menu() 148 | -------------------------------------------------------------------------------- /tokens.txt: -------------------------------------------------------------------------------- 1 | 68297mexdm1mpcus3mgrxmn836svuy 2 | kn19ca9bfnvdaelaz1za8sbc5x19eq 3 | kppti4iy4myrj69s0liehlfolc923i 4 | sqxc74m04knqpgohyaqs2lvh2u6zkm 5 | d9rdxp7iv0flnahlr62hu0jomq06pf 6 | rx4bnl08m5vttj1ioc32rqjdry1dph 7 | xzmbmj9ld2l7cgkcjvb5azowf4bw70 8 | uw5ob0bfnq3rxq6ywvl5dz8visawrz 9 | qkzo55ewr4vy3xr3yt6vlwmaevg8r5 10 | kuuo7huy4rqzdzyy6qsa3qex4vq7r8 11 | jl2rtutiegd0my4ncprqlvozro0zrb 12 | afe577rq89cvkiyvoavwxtwv15agam 13 | 9w70beygmlq8quxedowf1gcf3app6o 14 | lx67jq9bwpx4thgzdvprbgz028tlbj 15 | aa7ujiopt9i8l5aei2ve9itdk0y6ge 16 | myb48cti8ncfo7qx1978sdeev8obxg 17 | re28vttxt9keif0j83trqay6oy7q5x 18 | jhsuou3kzqujo9hg10bozvtpwh2mp2 19 | we02gxovin7ty2ylc0f8bi1qn25dpf 20 | nhugmiyg9t7ibvnn0lr84kbbuie19b 21 | tgcllmhmvn5euyw3e7atndttlgjlqo 22 | lyxagn9ofmlewshlkhk7du6k96mnhk 23 | ophxhw1umfa7ijik6zlvdeeyp081ft 24 | ebdv7dav0aeidb5g66l316vfaklrbd 25 | 2bvrwzf44cc5a0c985rt5pdjmdp37k 26 | o7adwsdp8ukj64dvkde0ols6hamsgk 27 | zhxbgniuw35tojvumvewghu9p0hkik 28 | 09154h1ofadp517rk00eapabyz26q8 29 | cdvyxnhwxyd4fhalmzqqui83k0umfp 30 | o4qejb33c8c2c7fz9x4suejve39n7s 31 | pv1umqg3xdewakcubdnbe20zun0p4w 32 | kmf0yirqb21c3ms7vpddx4g2qkurlc 33 | bsrp55fxf57p5juo76jb4mzwvr1rkk 34 | gc518js96ddu2ct60npzpsdnrvqsb9 35 | 94e2anbgf1d4oc2o0re8dj25hdvgm3 36 | 32qxwg6sljekcvrppy9vwkdkqmeyrr 37 | fo5pbf4n9zm6hdxn9laz0tofyv4obz 38 | qr2h9d39y8h83uej3c5gn4j0xxcxiw 39 | y5t04v8by1q0r5s1o2lnm9k3tunfu4 40 | ftblfoa7wq7rhzx7fdbru36dnet1nv 41 | sgmrj99ty83hx21th0qumewjs1x033 42 | 6qjlw0kque6trepigd7y2i1wbvu9jo 43 | rgdtto18ed31nm8ol1ajcbq604otsh 44 | amz6j1d3j5i9gy6q2ylyf0vvl9xgzr 45 | wscztkmf7wta8oy3ufnht3g21qfjnm 46 | 7up9ird22zc3d95vhismyiuae7f8rq 47 | 1sww3f8xs2tune1nt7r93x8xx3zhzx 48 | cpza6v4ym5xhrlmfc04j6ceulqiabv 49 | djimssz1guwqzpry6raxguq67zt3l9 50 | f5ck94l0lb1vz3x7yetf27u2fs4czl 51 | 4piy2t9fiu0egya2cstafywrggk74m 52 | xfszurgz07gaj2plau9t0j5v1uqx5i 53 | wnhewjcjskcfkqgcayx4gj0tvfvqae 54 | sqavv3hpnoz84bogqg20itk39y9ya3 55 | lltyiizqjtglmos6ge22mendaruhw1 56 | hpy0dkbj264qtrlm4lvqdpy3uyrpkf 57 | b8hmmnd57v40wim675pjrzi9kw79yr 58 | kn4dqk3gzp682kcm868mp6bfu5750o 59 | d998as48bxeloxt5l4vuexxv9vit9y 60 | vviudcrz0wf0dy2bbtrs0du4j5kdt5 61 | ca3edh4i0tekegnyxjk3ayuq5hxkg5 62 | 4z1j4k5bhkkhwisxp4ebwcsm7dsdy1 63 | mrp4nv49c1kbs5pu5pl08g2gmvauq4 64 | f2qr8n36b94vg8offvu04jsjvpvqxn 65 | x42uduztz5pzdi858hdk4mwtzqxzxz 66 | mn2zjahgbout3bvzia6miufxb9fh91 67 | 1o1b2x94obc724cs7gsiyab5ja81n8 68 | v4bdmiesw9o3oezfl9qvx8460mqx8d 69 | z2wynzfrdfnnfw2fox8iz1f0flj443 70 | d069j3aiy3e82909t7hhl8y0pv84je 71 | 18mwwc8cys7gw5rygrc1piqnh03otv 72 | 4rlhzja5wkvpn1tl3x5s3phl53t3d6 73 | cjwdh7nemf0k6rkw5ccdz03d0rjgmd 74 | 32a5g0xrtjgjrgc225rw6oqqjktm62 75 | bta0fuf2p6k6asgj1o1814zpb2t196 76 | t1mnz6d6g58wkfgcufffgmzmydnlh8 77 | 00xkw13kme3khi2kbrqwd4j686aj07 78 | j82iz4ld1vhxcdcjz41oa3miy756jf 79 | odk56w07wzhtfwgah0gd866h0rl64g 80 | fk4kkp0mqg8kvdmjd1ay6wv55u4kac 81 | sl1wj6hkr37bhpp1tuupvd8qwxuec8 82 | 6c1sslij3jmz31xuon4uoege76nzm1 83 | div2ba50gh4e4qc43111wmqqwtj8wq 84 | ligz1kivamq5xbl17q7dx3yjcuqbht 85 | ufran7p1yucy9y95xd2z8n74ghl78u 86 | 8pznjd3o9eg7npxickrl0jce09p9gi 87 | a8en4r1j0gjskke4mrkougtbw5ncry 88 | 697u7uato916tyxiw03tt5kpifmzsf 89 | o4syw6iqgf9j07uiq3mvsb9n4wss8a 90 | hxrfgzo4brs9ehtr7ij69hyzr3lpjl 91 | a1s1rw54awaiinqf762uinwotpndl9 92 | atb8ciiww4hfi4aqjm1g6jgnvvh7jy 93 | xgo6j3bzwfufosevlankkouh5q7k3s 94 | nsexwt79g9oim29ids4nc63ji61ctx 95 | y264v9exr1dg92sypw5acjzxm5y6qj 96 | bi0rsalsyzv32jh4s0rccq862qccbi 97 | --------------------------------------------------------------------------------