1"""Provide the WikiPage class.""" 2from ...const import API_PATH 3from ..listing.generator import ListingGenerator 4from .base import RedditBase 5from .redditor import Redditor 6 7 8class WikiPage(RedditBase): 9 """An individual WikiPage object. 10 11 **Typical Attributes** 12 13 This table describes attributes that typically belong to objects of this 14 class. Since attributes are dynamically provided (see 15 :ref:`determine-available-attributes-of-an-object`), there is not a 16 guarantee that these attributes will always be present, nor is this list 17 necessarily comprehensive. 18 19 ======================= =================================================== 20 Attribute Description 21 ======================= =================================================== 22 ``content_html`` The contents of the wiki page, as HTML. 23 ``content_md`` The contents of the wiki page, as Markdown. 24 ``may_revise`` A ``bool`` representing whether or not the 25 authenticated user may edit the wiki page. 26 ``name`` The name of the wiki page. 27 ``revision_by`` The :class:`.Redditor` who authored this 28 revision of the wiki page. 29 ``revision_date`` The time of this revision, in `Unix Time`_. 30 ``subreddit`` The :class:`.Subreddit` this wiki page belongs to. 31 ======================= =================================================== 32 33 .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time 34 """ 35 36 __hash__ = RedditBase.__hash__ 37 38 @staticmethod 39 def _revision_generator(subreddit, url, generator_kwargs): 40 for revision in ListingGenerator( 41 subreddit._reddit, url, **generator_kwargs 42 ): 43 if revision["author"] is not None: 44 revision["author"] = Redditor( 45 subreddit._reddit, _data=revision["author"]["data"] 46 ) 47 revision["page"] = WikiPage( 48 subreddit._reddit, subreddit, revision["page"], revision["id"] 49 ) 50 yield revision 51 52 @property 53 def mod(self): 54 """Provide an instance of :class:`.WikiPageModeration`.""" 55 if self._mod is None: 56 self._mod = WikiPageModeration(self) 57 return self._mod 58 59 def __eq__(self, other): 60 """Return whether the other instance equals the current.""" 61 return ( 62 isinstance(other, self.__class__) 63 and str(self).lower() == str(other).lower() 64 ) 65 66 def __init__(self, reddit, subreddit, name, revision=None, _data=None): 67 """Construct an instance of the WikiPage object. 68 69 :param revision: A specific revision ID to fetch. By default, fetches 70 the most recent revision. 71 72 """ 73 self.name = name 74 self._revision = revision 75 self.subreddit = subreddit 76 super(WikiPage, self).__init__(reddit, _data=_data) 77 self._mod = None 78 79 def __repr__(self): 80 """Return an object initialization representation of the instance.""" 81 return "{}(subreddit={!r}, name={!r})".format( 82 self.__class__.__name__, self.subreddit, self.name 83 ) 84 85 def __str__(self): 86 """Return a string representation of the instance.""" 87 return "{}/{}".format(self.subreddit, self.name) 88 89 def _fetch(self): 90 params = {"v": self._revision} if self._revision else None 91 data = self._reddit.get(self._info_path(), params=params)["data"] 92 if data["revision_by"] is not None: 93 data["revision_by"] = Redditor( 94 self._reddit, _data=data["revision_by"]["data"] 95 ) 96 self.__dict__.update(data) 97 self._fetched = True 98 99 def _info_path(self): 100 return API_PATH["wiki_page"].format( 101 subreddit=self.subreddit, page=self.name 102 ) 103 104 def edit(self, content, reason=None, **other_settings): 105 """Edit this WikiPage's contents. 106 107 :param content: The updated markdown content of the page. 108 :param reason: (Optional) The reason for the revision. 109 :param other_settings: Additional keyword arguments to pass. 110 111 """ 112 other_settings.update( 113 {"content": content, "page": self.name, "reason": reason} 114 ) 115 self._reddit.post( 116 API_PATH["wiki_edit"].format(subreddit=self.subreddit), 117 data=other_settings, 118 ) 119 120 def revision(self, revision): 121 """Return a specific version of this page by revision ID. 122 123 To view revision ``[ID]`` of ``'praw_test'`` in ``'/r/test'``: 124 125 .. code:: python 126 127 page = reddit.subreddit('test').wiki['praw_test'].revision('[ID]') 128 129 """ 130 return WikiPage( 131 self.subreddit._reddit, self.subreddit, self.name, revision 132 ) 133 134 def revisions(self, **generator_kwargs): 135 """Return a generator for page revisions. 136 137 Additional keyword arguments are passed in the initialization of 138 :class:`.ListingGenerator`. 139 140 To view the wiki revisions for ``'praw_test'`` in ``'/r/test'`` try: 141 142 .. code:: python 143 144 for item in reddit.subreddit('test').wiki['praw_test'].revisions(): 145 print(item) 146 147 To get :class:`.WikiPage` objects for each revision: 148 149 .. code:: python 150 151 for item in reddit.subreddit('test').wiki['praw_test'].revisions(): 152 print(item['page']) 153 154 """ 155 url = API_PATH["wiki_page_revisions"].format( 156 subreddit=self.subreddit, page=self.name 157 ) 158 return self._revision_generator(self.subreddit, url, generator_kwargs) 159 160 161class WikiPageModeration(object): 162 """Provides a set of moderation functions for a WikiPage.""" 163 164 def __init__(self, wikipage): 165 """Create a WikiPageModeration instance. 166 167 :param wikipage: The wikipage to moderate. 168 169 """ 170 self.wikipage = wikipage 171 172 def add(self, redditor): 173 """Add an editor to this WikiPage. 174 175 :param redditor: A redditor name (e.g., ``'spez'``) or 176 :class:`~.Redditor` instance. 177 178 To add ``'spez'`` as an editor on the wikipage ``'praw_test'`` try: 179 180 .. code:: python 181 182 reddit.subreddit('test').wiki['praw_test'].mod.add('spez') 183 184 """ 185 data = {"page": self.wikipage.name, "username": str(redditor)} 186 url = API_PATH["wiki_page_editor"].format( 187 subreddit=self.wikipage.subreddit, method="add" 188 ) 189 self.wikipage._reddit.post(url, data=data) 190 191 def remove(self, redditor): 192 """Remove an editor from this WikiPage. 193 194 :param redditor: A redditor name (e.g., ``'spez'``) or 195 :class:`~.Redditor` instance. 196 197 To remove ``'spez'`` as an editor on the wikipage ``'praw_test'`` try: 198 199 .. code:: python 200 201 reddit.subreddit('test').wiki['praw_test'].mod.remove('spez') 202 203 """ 204 data = {"page": self.wikipage.name, "username": str(redditor)} 205 url = API_PATH["wiki_page_editor"].format( 206 subreddit=self.wikipage.subreddit, method="del" 207 ) 208 self.wikipage._reddit.post(url, data=data) 209 210 def settings(self): 211 """Return the settings for this WikiPage.""" 212 url = API_PATH["wiki_page_settings"].format( 213 subreddit=self.wikipage.subreddit, page=self.wikipage.name 214 ) 215 return self.wikipage._reddit.get(url)["data"] 216 217 def update(self, listed, permlevel, **other_settings): 218 """Update the settings for this WikiPage. 219 220 :param listed: (boolean) Show this page on page list. 221 :param permlevel: (int) Who can edit this page? (0) use subreddit wiki 222 permissions, (1) only approved wiki contributors for this page may 223 edit (see :meth:`.WikiPageModeration.add`), (2) only mods may edit 224 and view 225 :param other_settings: Additional keyword arguments to pass. 226 :returns: The updated WikiPage settings. 227 228 To set the wikipage ``'praw_test'`` in ``'/r/test'`` to mod only and 229 disable it from showing in the page list, try: 230 231 .. code:: python 232 233 reddit.subreddit('test').wiki['praw_test'].mod.update(listed=False, 234 permlevel=2) 235 236 """ 237 other_settings.update({"listed": listed, "permlevel": permlevel}) 238 url = API_PATH["wiki_page_settings"].format( 239 subreddit=self.wikipage.subreddit, page=self.wikipage.name 240 ) 241 return self.wikipage._reddit.post(url, data=other_settings)["data"] 242