├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── mutuals.py └── secret.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | 3 | # for the love of all that is holy do not put this on github or anywhere else public 4 | secret.py 5 | 6 | # emacs shit 7 | *~ 8 | *# 9 | *.# -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO BUT IT'S NOT MY FAULT PUBLIC LICENSE 2 | Version 1, October 2013 3 | 4 | Copyright (C) 2013 Ben McGinnes 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO BUT IT'S NOT MY FAULT PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | 1. Do not hold the author(s), creator(s), developer(s) or 16 | distributor(s) liable for anything that happens or goes wrong 17 | with your use of the work. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # i am so sorry 2 | 3 | so u wanted to make a list of ur mutuals huh 4 | 5 | ## pre-reqs 6 | * u need `git` on ur system 7 | * u need to have ur user credentials from twitter dot com 8 | * go to step 1 [here](https://ageof.info/setting-up-twitter-bot-with-python-and-tweepy "link to da blog") to learn how to do this if u need help 9 | * put said credentials in the file titled `secret.py` as comments direct u 10 | * u need python > 3.5 11 | * not going to help you with this fam, i'm sorry, pls google it 12 | * once acquired, please enter `pip install tweepy` to install the necessary module 13 | * you might hit user permision issues, if so, `pip install --local tweepy` will probably work 14 | * do **not** use `sudo` 15 | * wu tang 16 | 17 | ## to run 18 | 1. clone this repository somewhere via `git clone https://github.com/ejmg/help-why-cant-i-hold-all-these-mutuals.git` 19 | 2. enter the directory 20 | 3. run `python3 mutuals.py` 21 | 4. if my code isn't too trash, you should get some output saying yay u did it or something 22 | 23 | ## if it doesn't work or something idk 24 | 25 | ᶦ ᵃᵐ ˢᵒ ˢᵒʳʳʸ 26 | 27 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ejmg/help-why-cant-i-hold-all-these-mutuals/26df54a00408e174ba3bcd474b6ee3b7fc8750ee/__init__.py -------------------------------------------------------------------------------- /mutuals.py: -------------------------------------------------------------------------------- 1 | """ 2 | mutuals.py 3 | ~~~~~~~~ 4 | 5 | so your first mistake was using my code, but since you are clearly reading this 6 | let it be known that mutuals.py lets you create a mutuals list on the hell 7 | site known as "twitter dot com". 8 | 9 | assuming you have python3 installed and your account credentials properly 10 | stored in secret.py, running `python3 mutuals.py` should do the trick. 11 | 12 | :copyright: @ 2018 13 | :author: elias julian marko garcia 14 | :license: WTFNMFPL, see LICENSE 15 | """ 16 | 17 | import tweepy as ty 18 | import time 19 | import sys 20 | from secret import (ACCESS_SECRET, ACCESS_TOKEN, CONSUMER_TOKEN, 21 | CONSUMER_SECRET) 22 | 23 | 24 | def setTwitterAuth(): 25 | """ 26 | obtains authorization from twitter API 27 | 28 | auth my ass, jack 29 | 30 | :return: api object for accessing user's twitter data 31 | """ 32 | # sets the auth tokens for twitter using tweepy 33 | auth = ty.OAuthHandler(CONSUMER_TOKEN, CONSUMER_SECRET) 34 | auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET) 35 | api = ty.API(auth) 36 | return api 37 | 38 | 39 | def handleCursorLimit(cursor): 40 | """ 41 | can u handle the limit????? 42 | 43 | handles limit errors caused by calls to twitter's api through their cursor 44 | feature. 45 | 46 | :param cursor: cursor iterator for finding all friends 47 | :return: yields the next cursor to iterate over 48 | """ 49 | while True: 50 | try: 51 | yield cursor.next() 52 | except ty.RateLimitError: 53 | print("you must have a lot of mutuals or something because we have" 54 | " have officially just hit twitter's api limit. give it some" 55 | " some time to reset, ~15 mins, and the script will pickup") 56 | print("sleeping! {}".format(time.localtime())) 57 | # got fucked by jack's api once again, press F please 58 | time.sleep(60 * 15) 59 | 60 | 61 | def mutuals(api): 62 | """ 63 | this is the actual meat of the script. gathers a list of your friends, 64 | checks for mutual status, and creates a list of them. 65 | 66 | if you are wondering what the fuck i'm doing with these try catches, 67 | blame the fact twitter only partially implements pagination in their 68 | api, thus defeating a very useful/clean feature for handling api 69 | limit exceptions. 70 | 71 | :param api: api object necessary to access user's account data 72 | """ 73 | thyself = api.me().id 74 | iCanCountLol = 0 75 | mutualists = [] 76 | # debugging 77 | # print("Your user ID number: {}".format(thyself)) 78 | 79 | for fran in handleCursorLimit(ty.Cursor(api.friends).items()): 80 | # debugging 81 | # print("fran: {}".format(fran.id)) 82 | 83 | # technically speaking, this api request can still fuck us over and 84 | # sideways, so let us pray together very very very very hard that the 85 | # magic dice of the universe roll our way on this request. 86 | for _ in range(11): 87 | try: 88 | franship = api.show_friendship( 89 | source_id=thyself, target_id=fran.id) 90 | 91 | if franship[0].following and franship[0].followed_by: 92 | iCanCountLol += 1 93 | mutualists.append(franship[1].id) 94 | print("{} is a mutual!".format(franship[1].screen_name)) 95 | 96 | # we have made it out alive.... for now. @jack's bloodlust 97 | # goes unsatiated nonetheless. 98 | break 99 | 100 | except ty.RateLimitError: 101 | print("we hit the rate error, @jack is not pleased." 102 | "give the script ~15 mins to finish what it is doing.") 103 | # we must satiate @jack's thirst for wasted cpu cycles 104 | time.sleep(60 * 15) 105 | continue 106 | 107 | except Exception as e: 108 | print( 109 | "something really goofed up in the process of finding your" 110 | " friends. Assuming they exist, then it is probably just" 111 | " my shitty code. Error: {}".format(e)) 112 | sys.exit() 113 | 114 | print("Assuming shit is not whack and my code is not whack, you" 115 | " have {} mutuals".format(iCanCountLol)) 116 | 117 | print("we will now create the list. give me a quick sec") 118 | 119 | # this will create the list. if you have a list of the same name, 120 | # afaik, twitter makes a list with the same name, but its "slug" 121 | # willbe the list name + digit, where digit = # duplicate 122 | 123 | # also lol what are api limit checks yet again also lol let's talk 124 | # about side effects in code because what the fuck is this list api 125 | # creation method hahahahahahahahahahahahahahahahaha 126 | myOwnStasi = api.create_list("mutuals").id 127 | for muchie in mutualists: 128 | for _ in range(11): 129 | try: 130 | api.add_list_member( 131 | user_id=muchie, list_id=myOwnStasi, owner_id=thyself) 132 | break 133 | except ty.RateLimitError: 134 | print("we hit the rate error, @jack is not pleased." 135 | "give the script ~15 mins to finish what it is" 136 | " doing.") 137 | # we must satiate @jack's thirst for wasted cpu cycles 138 | time.sleep(60 * 15) 139 | continue 140 | 141 | except Exception as e: 142 | print("wtf i make horrible code, exception while" 143 | " making list: {}".format(e)) 144 | print("muchie value: {} \nlist_id value: {} \nowner_id" 145 | " value: {}".format(muchie, myOwnStasi, thyself)) 146 | print("the code is going to exit, dm me or cry on github" 147 | " to see if i" 148 | " can fix my code (narrator voice: he might not do" 149 | " it)") 150 | sys.exit() 151 | 152 | # lol 153 | print("Tada it worked or something, go check it out on twitter dot com and" 154 | " see for urself ") 155 | 156 | 157 | if __name__ == '__main__': 158 | print("i am so sorry mom i could have been a real engineer") 159 | api = setTwitterAuth() 160 | mutuals(api) 161 | -------------------------------------------------------------------------------- /secret.py: -------------------------------------------------------------------------------- 1 | """ 2 | Insert the values you find at https://apps.twitter.com/ below in their 3 | corresponding variable **between** the single quotes for each. 4 | 5 | If you do not have your user credentials created yet, go to step 1 of this 6 | blog post which describes how to create these values: 7 | https://ageof.info/setting-up-twitter-bot-with-python-and-tweepy.html 8 | """ 9 | 10 | CONSUMER_TOKEN = '' 11 | CONSUMER_SECRET = '' 12 | ACCESS_TOKEN = '' 13 | ACCESS_SECRET = '' 14 | --------------------------------------------------------------------------------